2 rcs_id('$Id: Template.php,v 1.79 2007-09-15 12:28:46 rurban Exp $');
4 require_once("lib/ErrorManager.php");
12 * name optionally of form "theme/template" to include parent templates in children
14 function Template ($name, &$request, $args = false) {
17 $this->_request =& $request;
18 $this->_basepage = $request->getArg('pagename');
20 if (strstr($name, "/")) {
21 $oldname = $WikiTheme->_name;
22 $oldtheme = $WikiTheme->_theme;
23 list($themename, $name) = explode("/", $name);
24 $WikiTheme->_theme = "themes/$themename";
25 $WikiTheme->_name = $name;
28 $file = $WikiTheme->findTemplate($name);
30 trigger_error("no template for $name found.", E_USER_WARNING);
33 if (isset($oldname)) {
34 $WikiTheme->_name = $oldname;
35 $WikiTheme->_theme = $oldtheme;
37 $fp = fopen($file, "rb");
39 trigger_error("$file not found", E_USER_WARNING);
42 $request->_TemplatesProcessed[$name] = 1;
43 $this->_tmpl = fread($fp, filesize($file));
45 //$userid = $request->_user->_userid;
47 $this->_locals = $args;
49 $this->_locals = array('CONTENT' => $args);
51 $this->_locals = array();
54 function _munge_input($template) {
56 // Convert < ?plugin expr ? > to < ?php $this->_printPluginPI("expr"); ? >
57 $orig[] = '/<\?plugin.*?\?>/se';
58 $repl[] = "\$this->_mungePlugin('\\0')";
60 // Convert < ?= expr ? > to < ?php $this->_print(expr); ? >
61 $orig[] = '/<\?=(.*?)\?>/s';
62 $repl[] = '<?php $this->_print(\1);?>';
64 return preg_replace($orig, $repl, $template);
67 function _mungePlugin($pi) {
68 // HACK ALERT: PHP's preg_replace, with the /e option seems to
69 // escape both single and double quotes with backslashes.
70 // So we need to unescape the double quotes here...
72 $pi = preg_replace('/(?!<\\\\)\\\\"/x', '"', $pi);
73 return sprintf('<?php $this->_printPlugin(%s); ?>',
74 "'" . str_replace("'", "\'", $pi) . "'");
77 function _printPlugin ($pi) {
78 include_once("lib/WikiPlugin.php");
82 $loader = new WikiPluginLoader;
84 $this->_print($loader->expandPI($pi, $this->_request, $this, $this->_basepage));
87 function _print ($val) {
88 if (isa($val, 'Template')) {
89 $this->_expandSubtemplate($val);
95 function _expandSubtemplate (&$template) {
97 //if (!$template->_request)
98 // $template->_request = &$this->_request;
100 echo "<!-- Begin $template->_name -->\n";
102 // Expand sub-template with defaults from this template.
103 $template->printExpansion($this->_vars);
105 echo "<!-- End $template->_name -->\n";
110 * Substitute HTML replacement text for tokens in template.
112 * Constructs a new WikiTemplate based upon the named template.
116 * @param $token string Name of token to substitute for.
118 * @param $replacement string Replacement HTML text.
120 function replace($varname, $value) {
121 $this->_locals[$varname] = $value;
125 function printExpansion ($defaults = false) {
126 if (!is_array($defaults)) // HTML object or template object
127 $defaults = array('CONTENT' => $defaults);
128 $this->_vars = array_merge($defaults, $this->_locals);
129 extract($this->_vars);
133 $user = $request->getUser();
135 $page = $request->getPage();
136 // Speedup. I checked all templates
137 if (!isset($revision))
140 global $WikiTheme, $RCS_IDS, $charset;
141 //$this->_dump_template();
142 $SEP = $WikiTheme->getButtonSeparator();
144 global $ErrorManager;
145 $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_errorHandler'));
147 eval('?>' . $this->_munge_input($this->_tmpl));
149 $ErrorManager->popErrorHandler();
153 // Find a way to do template expansion less memory intensive and faster.
154 // 1.3.4 needed no memory at all for dumphtml, now it needs +15MB.
155 // Smarty? As before?
156 function getExpansion ($defaults = false) {
158 $this->printExpansion($defaults);
159 $xml = ob_get_contents();
160 ob_end_clean(); // PHP problem: Doesn't release its memory?
164 function printXML () {
165 $this->printExpansion();
169 return $this->getExpansion();
174 function _dump_template () {
175 $lines = explode("\n", $this->_munge_input($this->_tmpl));
178 foreach ($lines as $line)
179 $pre->pushContent(fmt("%4d %s\n", $n++, $line));
183 function _errorHandler($error) {
184 //if (!preg_match('/: eval\(\)\'d code$/', $error->errfile))
187 if (preg_match('/: eval\(\)\'d code$/', $error->errfile)) {
188 $error->errfile = "In template '$this->_name'";
189 // Hack alert: Ignore 'undefined variable' messages for variables
190 // whose names are ALL_CAPS.
191 if (preg_match('/Undefined variable:\s*[_A-Z]+\s*$/', $error->errstr))
194 // ignore recursively nested htmldump loop: browse -> body -> htmldump -> browse -> body ...
195 // FIXME for other possible loops also
196 elseif (strstr($error->errfile, "In template 'htmldump'")) {
199 elseif (strstr($error->errfile, "In template '")) { // merge
200 $error->errfile = preg_replace("/'(\w+)'\)$/", "'\\1' < '$this->_name')", $error->errfile);
203 $error->errfile .= " (In template '$this->_name')";
206 if (!empty($this->_tmpl)) {
207 $lines = explode("\n", $this->_tmpl);
208 if (isset($lines[$error->errline - 1]))
209 $error->errstr .= ":\n\t" . $lines[$error->errline - 1];
218 * This is a convenience function and is equivalent to:
223 function Template($name, $args = false) {
225 return new Template($name, $request, $args);
228 function alreadyTemplateProcessed($name) {
230 return !empty($request->_TemplatesProcessed[$name]) ? true : false;
233 * Make and expand the top-level template.
236 * @param $content mixed html content to put into the page
237 * @param $title string page title
238 * @param $page_revision object A WikiDB_PageRevision object or false
239 * @param $args hash Extract args for top-level template
241 * @return string HTML expansion of template.
243 function GeneratePage($content, $title, $page_revision = false, $args = false) {
246 if (!is_array($args))
249 $args['CONTENT'] = $content;
250 $args['TITLE'] = $title;
251 $args['revision'] = $page_revision;
253 if (!isset($args['HEADER']))
254 $args['HEADER'] = $title;
256 printXML(new Template('html', $request, $args));
261 * For dumping pages as html to a file.
262 * Used for action=dumphtml,action=ziphtml,format=pdf,format=xml
264 function GeneratePageasXML($content, $title, $page_revision = false, $args = false) {
267 if (!is_array($args))
270 $content->_basepage = $title;
271 $args['CONTENT'] = $content;
272 $args['TITLE'] = SplitPagename($title);
273 $args['revision'] = $page_revision;
275 if (!isset($args['HEADER']))
276 $args['HEADER'] = SplitPagename($title);
278 global $HIDE_TOOLBARS, $NO_BASEHREF, $WikiTheme;
279 $HIDE_TOOLBARS = true;
280 if (!$WikiTheme->DUMP_MODE)
281 $WikiTheme->DUMP_MODE = 'HTML';
283 // FIXME: unfatal errors and login requirements
284 $html = asXML(new Template('htmldump', $request, $args));
286 $HIDE_TOOLBARS = false;
287 //$WikiTheme->DUMP_MODE = false;
291 // $Log: not supported by cvs2svn $
292 // Revision 1.78 2007/09/12 19:32:29 rurban
293 // link only VALID_LINKS with pagelist HTML_DUMP
295 // Revision 1.77 2007/07/14 19:17:57 rurban
296 // fix template inclusion with a recursion cycle leading e.g. to crashes in blog PageInfo
298 // Revision 1.76 2007/05/13 18:13:04 rurban
299 // Protect against erronously closed template file
301 // Revision 1.75 2007/01/02 13:18:55 rurban
302 // speed up Template expansion. revision only necessary. fixed all affected templates
304 // Revision 1.73 2005/04/08 05:41:00 rurban
305 // fix Template("theme/name") inclusion
307 // Revision 1.72 2005/02/02 20:35:41 rurban
310 // Revision 1.71 2005/02/02 19:29:30 rurban
311 // support theme overrides
313 // Revision 1.70 2005/01/25 07:01:26 rurban
314 // update comments about future plans
316 // Revision 1.69 2004/11/17 20:07:17 rurban
319 // Revision 1.68 2004/11/09 17:11:04 rurban
320 // * revert to the wikidb ref passing. there's no memory abuse there.
321 // * use new wikidb->_cache->_id_cache[] instead of wikidb->_iwpcache, to effectively
322 // store page ids with getPageLinks (GleanDescription) of all existing pages, which
323 // are also needed at the rendering for linkExistingWikiWord().
324 // pass options to pageiterator.
325 // use this cache also for _get_pageid()
326 // This saves about 8 SELECT count per page (num all pagelinks).
327 // * fix passing of all page fields to the pageiterator.
328 // * fix overlarge session data which got broken with the latest ACCESS_LOG_SQL changes
330 // Revision 1.67 2004/11/05 18:03:35 rurban
331 // shorten the template chain in errmsg
333 // Revision 1.66 2004/11/01 10:43:55 rurban
334 // seperate PassUser methods into seperate dir (memory usage)
335 // fix WikiUser (old) overlarge data session
336 // remove wikidb arg from various page class methods, use global ->_dbi instead
339 // Revision 1.65 2004/10/07 16:08:58 rurban
340 // fixed broken FileUser session handling.
341 // thanks to Arnaud Fontaine for detecting this.
342 // enable file user Administrator membership.
344 // Revision 1.64 2004/10/04 23:40:35 rurban
345 // fix nested loops on htmldump errors
347 // Revision 1.63 2004/09/06 08:22:33 rurban
348 // prevent errorhandler to fail on empty templates
350 // Revision 1.62 2004/06/28 15:39:27 rurban
351 // fixed endless recursion in WikiGroup: isAdmin()
353 // Revision 1.61 2004/06/25 14:29:18 rurban
354 // WikiGroup refactoring:
355 // global group attached to user, code for not_current user.
356 // improved helpers for special groups (avoid double invocations)
357 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
358 // fixed a XHTML validation error on userprefs.tmpl
360 // Revision 1.60 2004/06/14 11:31:36 rurban
361 // renamed global $Theme to $WikiTheme (gforge nameclash)
362 // inherit PageList default options from PageList
363 // default sortby=pagename
364 // use options in PageList_Selectable (limit, sortby, ...)
365 // added action revert, with button at action=diff
366 // added option regex to WikiAdminSearchReplace
368 // Revision 1.59 2004/05/18 16:23:39 rurban
369 // rename split_pagename to SplitPagename
371 // Revision 1.58 2004/05/15 19:48:33 rurban
372 // fix some too loose PagePerms for signed, but not authenticated users
373 // (admin, owner, creator)
374 // no double login page header, better login msg.
375 // moved action_pdf to lib/pdf.php
377 // Revision 1.57 2004/05/01 18:20:05 rurban
378 // Add $charset to template locals (instead of constant CHARSET)
380 // Revision 1.56 2004/04/12 13:04:50 rurban
381 // added auth_create: self-registering Db users
383 // removed rating recommendations
384 // ziplib reformatting
386 // Revision 1.55 2004/04/02 15:06:55 rurban
387 // fixed a nasty ADODB_mysql session update bug
388 // improved UserPreferences layout (tabled hints)
389 // fixed UserPreferences auth handling
390 // improved auth stability
391 // improved old cookie handling: fixed deletion of old cookies with paths
393 // Revision 1.54 2004/03/02 18:11:39 rurban
394 // CreateToc support: Pass the preparsed markup to each plugin as $dbi->_markup
395 // to be able to know about its context, and even let the plugin change it.
398 // Revision 1.53 2004/02/22 23:20:31 rurban
399 // fixed DumpHtmlToDir,
400 // enhanced sortby handling in PageList
401 // new button_heading th style (enabled),
402 // added sortby and limit support to the db backends and plugins
403 // for paging support (<<prev, next>> links on long lists)
405 // Revision 1.52 2003/12/20 23:59:19 carstenklapp
406 // Internal change: Added rcs Log tag & emacs php mode tag (sorry, forgot
407 // this in the last commit).
414 // c-hanging-comment-ender-p: nil
415 // indent-tabs-mode: nil