]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/Template.php
Reformat code
[SourceForge/phpwiki.git] / lib / Template.php
1 <?php
2
3 require_once 'lib/ErrorManager.php';
4
5 /** An HTML template.
6  */
7 class Template
8 {
9     /**
10      * name optionally of form "theme/template" to include parent templates in children
11      */
12     function Template($name, &$request, $args = false)
13     {
14         global $WikiTheme;
15
16         $this->_request =& $request;
17         $this->_basepage = $request->getArg('pagename');
18
19         if (strstr($name, "/")) {
20             $oldname = $WikiTheme->_name;
21             $oldtheme = $WikiTheme->_theme;
22             list($themename, $name) = explode("/", $name);
23             $WikiTheme->_theme = "themes/$themename";
24             $WikiTheme->_name = $name;
25         }
26         $this->_name = $name;
27         $file = $WikiTheme->findTemplate($name);
28         if (!$file) {
29             trigger_error("no template for $name found.", E_USER_WARNING);
30             return;
31         }
32         if (isset($oldname)) {
33             $WikiTheme->_name = $oldname;
34             $WikiTheme->_theme = $oldtheme;
35         }
36         $fp = fopen($file, "rb");
37         if (!$fp) {
38             trigger_error("$file not found", E_USER_WARNING);
39             return;
40         }
41         $request->_TemplatesProcessed[$name] = 1;
42         $this->_tmpl = fread($fp, filesize($file));
43         if ($fp) fclose($fp);
44         //$userid = $request->_user->_userid;
45         if (is_array($args))
46             $this->_locals = $args;
47         elseif ($args)
48             $this->_locals = array('CONTENT' => $args); else
49             $this->_locals = array();
50     }
51
52     function _munge_input($template)
53     {
54
55         // Convert < ?plugin expr ? > to < ?php $this->_printPluginPI("expr"); ? >
56         $orig[] = '/<\?plugin.*?\?>/se';
57         $repl[] = "\$this->_mungePlugin('\\0')";
58
59         // Convert < ?= expr ? > to < ?php $this->_print(expr); ? >
60         $orig[] = '/<\?=(.*?)\?>/s';
61         $repl[] = '<?php $this->_print(\1);?>';
62
63         // Convert < ?php echo expr ? > to < ?php $this->_print(expr); ? >
64         $orig[] = '/<\?php echo (.*?)\?>/s';
65         $repl[] = '<?php $this->_print(\1);?>';
66
67         return preg_replace($orig, $repl, $template);
68     }
69
70     function _mungePlugin($pi)
71     {
72         // HACK ALERT: PHP's preg_replace, with the /e option seems to
73         // escape both single and double quotes with backslashes.
74         // So we need to unescape the double quotes here...
75
76         $pi = preg_replace('/(?!<\\\\)\\\\"/x', '"', $pi);
77         return sprintf('<?php $this->_printPlugin(%s); ?>',
78             "'" . str_replace("'", "\'", $pi) . "'");
79     }
80
81     function _printPlugin($pi)
82     {
83         include_once 'lib/WikiPlugin.php';
84         static $loader;
85
86         if (empty($loader))
87             $loader = new WikiPluginLoader;
88
89         $this->_print($loader->expandPI($pi, $this->_request, $this, $this->_basepage));
90     }
91
92     function _print($val)
93     {
94         if (isa($val, 'Template')) {
95             $this->_expandSubtemplate($val);
96         } else {
97             PrintXML($val);
98         }
99     }
100
101     function _expandSubtemplate(&$template)
102     {
103         // FIXME: big hack!
104         //if (!$template->_request)
105         //    $template->_request = &$this->_request;
106         if (DEBUG) {
107             echo "<!-- Begin $template->_name -->\n";
108         }
109         // Expand sub-template with defaults from this template.
110         $template->printExpansion($this->_vars);
111         if (DEBUG) {
112             echo "<!-- End $template->_name -->\n";
113         }
114     }
115
116     /**
117      * Substitute HTML replacement text for tokens in template.
118      *
119      * Constructs a new WikiTemplate based upon the named template.
120      *
121      * @access public
122      *
123      * @param $token string Name of token to substitute for.
124      *
125      * @param $replacement string Replacement HTML text.
126      */
127     function replace($varname, $value)
128     {
129         $this->_locals[$varname] = $value;
130     }
131
132
133     function printExpansion($defaults = false)
134     {
135         if (!is_array($defaults)) // HTML object or template object
136             $defaults = array('CONTENT' => $defaults);
137         $this->_vars = array_merge($defaults, $this->_locals);
138         extract($this->_vars);
139
140         global $request;
141         if (!isset($user))
142             $user = $request->getUser();
143         if (!isset($page))
144             $page = $request->getPage();
145         // Speedup. I checked all templates
146         if (!isset($revision))
147             $revision = false;
148
149         global $WikiTheme, $charset;
150         //$this->_dump_template();
151         $SEP = $WikiTheme->getButtonSeparator();
152
153         global $ErrorManager;
154         $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_errorHandler'));
155
156         eval('?>' . $this->_munge_input($this->_tmpl));
157
158         $ErrorManager->popErrorHandler();
159     }
160
161     // FIXME (1.3.12)
162     // Find a way to do template expansion less memory intensive and faster.
163     // 1.3.4 needed no memory at all for dumphtml, now it needs +15MB.
164     // Smarty? As before?
165     function getExpansion($defaults = false)
166     {
167         ob_start();
168         $this->printExpansion($defaults);
169         $xml = ob_get_contents();
170         ob_end_clean(); // PHP problem: Doesn't release its memory?
171         return $xml;
172     }
173
174     function printXML()
175     {
176         $this->printExpansion();
177     }
178
179     function asXML()
180     {
181         return $this->getExpansion();
182     }
183
184
185     // Debugging:
186     function _dump_template()
187     {
188         $lines = explode("\n", $this->_munge_input($this->_tmpl));
189         $pre = HTML::pre();
190         $n = 1;
191         foreach ($lines as $line)
192             $pre->pushContent(fmt("%4d  %s\n", $n++, $line));
193         $pre->printXML();
194     }
195
196     function _errorHandler($error)
197     {
198         //if (!preg_match('/: eval\(\)\'d code$/', $error->errfile))
199         //    return false;
200
201         if (preg_match('/: eval\(\)\'d code$/', $error->errfile)) {
202             $error->errfile = "In template '$this->_name'";
203             // Hack alert: Ignore 'undefined variable' messages for variables
204             //  whose names are ALL_CAPS.
205             if (preg_match('/Undefined variable:\s*[_A-Z]+\s*$/', $error->errstr))
206                 return true;
207         } // ignore recursively nested htmldump loop: browse -> body -> htmldump -> browse -> body ...
208         // FIXME for other possible loops also
209         elseif (strstr($error->errfile, "In template 'htmldump'")) {
210             ; //return $error;
211         } elseif (strstr($error->errfile, "In template '")) { // merge
212             $error->errfile = preg_replace("/'(\w+)'\)$/", "'\\1' < '$this->_name')",
213                 $error->errfile);
214         } else {
215             $error->errfile .= " (In template '$this->_name')";
216         }
217
218         if (!empty($this->_tmpl)) {
219             $lines = explode("\n", $this->_tmpl);
220             if (isset($lines[$error->errline - 1]))
221                 $error->errstr .= ":\n\t" . $lines[$error->errline - 1];
222         }
223         return $error;
224     }
225 }
226
227 ;
228
229 /**
230  * Get a templates
231  *
232  * This is a convenience function and is equivalent to:
233  * <pre>
234  *   new Template(...)
235  * </pre>
236  */
237 function Template($name, $args = false)
238 {
239     global $request;
240     return new Template($name, $request, $args);
241 }
242
243 function alreadyTemplateProcessed($name)
244 {
245     global $request;
246     return !empty($request->_TemplatesProcessed[$name]) ? true : false;
247 }
248
249 /**
250  * Make and expand the top-level template.
251  *
252  *
253  * @param $content mixed html content to put into the page
254  * @param $title string page title
255  * @param $page_revision object A WikiDB_PageRevision object or false
256  * @param $args hash Extract args for top-level template
257  *
258  * @return string HTML expansion of template.
259  */
260 function GeneratePage($content, $title, $page_revision = false, $args = false)
261 {
262     global $request;
263
264     if (!is_array($args))
265         $args = array();
266
267     $args['CONTENT'] = $content;
268     $args['TITLE'] = $title;
269     $args['revision'] = $page_revision;
270
271     if (!isset($args['HEADER']))
272         $args['HEADER'] = $title;
273
274     printXML(new Template('html', $request, $args));
275 }
276
277
278 /**
279  * For dumping pages as html to a file.
280  * Used for action=dumphtml,action=ziphtml,format=pdf,format=xml
281  */
282 function GeneratePageasXML($content, $title, $page_revision = false, $args = false)
283 {
284     global $request;
285
286     if (!is_array($args))
287         $args = array();
288
289     $content->_basepage = $title;
290     $args['CONTENT'] = $content;
291     $args['TITLE'] = SplitPagename($title);
292     $args['revision'] = $page_revision;
293
294     if (!isset($args['HEADER']))
295         $args['HEADER'] = SplitPagename($title);
296
297     global $HIDE_TOOLBARS, $NO_BASEHREF, $WikiTheme;
298     $HIDE_TOOLBARS = true;
299     if (!$WikiTheme->DUMP_MODE)
300         $WikiTheme->DUMP_MODE = 'HTML';
301
302     // FIXME: unfatal errors and login requirements
303     $html = asXML(new Template('htmldump', $request, $args));
304
305     $HIDE_TOOLBARS = false;
306     //$WikiTheme->DUMP_MODE = false;
307     return $html;
308 }
309
310 // Local Variables:
311 // mode: php
312 // tab-width: 8
313 // c-basic-offset: 4
314 // c-hanging-comment-ender-p: nil
315 // indent-tabs-mode: nil
316 // End: