1 <?php rcs_id('$Id: Template.php,v 1.4 2001-11-29 02:59:21 dairiki Exp $');
3 require_once("lib/ErrorManager.php");
4 require_once("lib/WikiPlugin.php");
6 //FIXME: This is a mess and needs to be refactored.
7 // (In other words: this is all in a state of flux, so don't count on any
8 // of this being the same tomorrow...)
12 function Template($tmpl) {
13 //$this->_tmpl = $this->_munge_input($tmpl);
15 $this->_vars = array();
18 function _munge_input($template) {
19 // Expand "< ?plugin-* ...? >"
20 preg_match_all('/<\?plugin.*?\?>/s', $template, $m);
21 global $dbi, $request; // FIXME: no globals?
22 $pluginLoader = new WikiPluginLoader;
23 foreach (array_unique($m[0]) as $plugin_pi) {
24 $orig[] = '/' . preg_quote($plugin_pi, '/') . '/s';
25 // Plugin args like 'description=_("Get backlinks")' get
27 // FIXME: move this to WikiPlugin.php.
28 $translated_pi = preg_replace('/(\s\w+=)_\("((?:[^"\\\\]|\\.)*)"\)/xse',
29 '"\1\"" . gettext("\2") . "\""',
31 $repl[] = $pluginLoader->expandPI($translated_pi, $dbi, $request);
34 // Convert ${VAR} to < ?php echo "$VAR"; ? >
35 //$orig[] = '/\${(\w[\w\d]*)}/';
36 //$repl[] = '<?php echo "$\1"; ? >';
37 $orig[] = '/\${(\w[\w\d]*)}/e';
38 $repl[] = '$this->_getReplacement("\1")';
40 // Convert $VAR[ind] to < ?php echo "$VAR[ind]"; ? >
41 $orig[] = '/\$(\w[\w\d]*)\[([\w\d]+)\]/e';
42 $repl[] = '$this->_getReplacement("\1", "\2")';
44 // Convert $_("String") to < ?php echo htmlspecialchars(gettext("String")); ? >
45 $orig[] = '/\$_\(("(?:[^"\\\\]|\\.)*")\)/xs';
46 $repl[] = "<?php echo htmlspecialchars(gettext(\\1)); ?>";
48 // Convert tag attributes like foo=_("String") to foo="String" (with gettext mapping).
49 $orig[] = '/( < \w [^>]* \w=)_\("((?:[^"\\\\]|\\.)*)"\)/xse';
50 $repl[] = '"\1\"" . htmlspecialchars(gettext("\2")) . "\""';
52 return preg_replace($orig, $repl, $template);
54 $ret = preg_replace($orig, $repl, $template);
55 echo QElement('pre', $ret);
61 function _getReplacement($varname, $index = false) {
62 // FIXME: report missing vars.
63 $vars = &$this->_vars;
64 if (isset($vars[$varname])) {
65 $value = $vars[$varname];
67 @$value = (string) $value[$index];
68 return str_replace('?', '?', $value);
74 * Substitute HTML replacement text for tokens in template.
76 * Constructs a new WikiTemplate based upon the named template.
80 * @param $token string Name of token to substitute for.
82 * @param $replacement string Replacement HTML text.
84 function replace($varname, $value) {
85 $this->_vars[$varname] = $value;
89 * Substitute text for tokens in template.
93 * @param $token string Name of token to substitute for.
95 * @param $replacement string Replacement text.
96 * The replacement text is run through htmlspecialchars()
97 * to escape any special characters.
99 function qreplace($varname, $value) {
100 $this->_vars[$varname] = htmlspecialchars($value);
105 * Include/remove conditional text in template.
109 * @param $token string Conditional token name.
110 * The text within any matching if blocks (or single line ifs) will
111 * be included in the template expansion, while the text in matching
112 * negated if blocks will be excluded.
115 function setConditional($token, $value = true) {
116 $this->_iftoken[$token] = $value;
120 function getExpansion($varhash = false) {
121 $savevars = $this->_vars;
122 if (is_array($varhash)) {
123 foreach ($varhash as $key => $val)
124 $this->_vars[$key] = $val;
126 extract($this->_vars);
127 if (isset($this->_iftoken))
128 $_iftoken = $this->_iftoken;
132 //$this->_dump_template();
134 global $ErrorManager;
135 $ErrorManager->pushErrorHandler(new WikiMethodCb($this, '_errorHandler'));
136 eval('?>' . $this->_munge_input($this->_tmpl));
137 $ErrorManager->popErrorHandler();
139 $html = ob_get_contents();
145 function printExpansion($args = false) {
146 echo $this->getExpansion($args);
150 function _dump_template () {
151 $lines = explode("\n", $this->_munge_input($this->_tmpl));
154 foreach ($lines as $line)
155 printf("%4d %s\n", $n++, htmlspecialchars($line));
159 function _errorHandler($error) {
160 if (!preg_match('/: eval\(\)\'d code$/', $error->errfile))
162 $error->errfile = "In template";
163 $lines = explode("\n", $this->_tmpl);
164 if (isset($lines[$error->errline - 1]))
165 $error->errstr .= ":\n\t" . $lines[$error->errline - 1];
173 function TemplateFile($filename) {
174 $this->_template_file = $filename;
175 $fp = fopen($filename, "rb");
176 $data = fread($fp, filesize($filename));
178 $this->Template($data);
188 * Constructs a new WikiTemplate based upon the named template.
192 * @param $template string Which template.
194 function WikiTemplate($template, $page_revision = false) {
197 $this->TemplateFile(FindFile($templates[$template]));
199 $this->_template_name = $template;
201 $this->setGlobalTokens();
203 $this->setPageRevisionTokens($page_revision);
207 function setPageTokens(&$page) {
209 if ($page->get('locked'))
210 $this->setConditional('LOCK');
211 // HACK: note that EDITABLE may also be set in setWikiUserTokens.
212 if (!$page->get('locked'))
213 $this->setConditional('EDITABLE');
216 $pagename = $page->getName();
217 $this->replace('page', $page);
218 $this->qreplace('PAGE', $pagename);
219 $this->qreplace('PAGEURL', rawurlencode($pagename));
220 $this->qreplace('SPLIT_PAGE', split_pagename($pagename));
221 $this->qreplace('BROWSE_PAGE', WikiURL($pagename));
223 // FIXME: this is a bit of dangerous hackage.
224 $this->qreplace('ACTION', WikiURL($pagename, array('action' => '')));
227 //$this->replace_callback('HITS', array($page, 'getHitCount'));
228 //$this->replace_callback('RELATEDPAGES', array($page, 'getHitCount'));
229 //_dotoken('RELATEDPAGES', LinkRelatedPages($dbi, $name), $page);
232 function setPageRevisionTokens(&$revision) {
233 $page = & $revision->getPage();
235 $current = & $page->getCurrentRevision();
236 $previous = & $page->getRevisionBefore($revision->getVersion());
238 $this->replace('IS_CURRENT',
239 $current->getVersion() == $revision->getVersion());
242 if ($previous && $previous->getVersion() != 0)
243 $this->setConditional('COPY'); // FIXME: should rename HAVE_COPY?
246 global $datetimeformat;
248 $this->qreplace('LASTMODIFIED',
249 strftime($datetimeformat, $revision->get('mtime')));
250 $this->qreplace('LASTAUTHOR', $revision->get('author'));
251 $this->qreplace('VERSION', $revision->getVersion());
252 $this->qreplace('CURRENT_VERSION', $current->getVersion());
254 $this->setPageTokens($page);
257 function setWikiUserTokens(&$user) {
259 if ( $user->is_admin() ) {
260 $this->setConditional('ADMIN');
261 $this->setConditional('EDITABLE');
263 if ( ! $user->is_authenticated() )
264 $this->setConditional('ANONYMOUS');
266 $this->replace('user', $user);
267 $this->qreplace('USERID', $user->id());
268 $prefs = $user->getPreferences();
269 $this->qreplace('EDIT_AREA_WIDTH', $prefs['edit_area.width']);
270 $this->qreplace('EDIT_AREA_HEIGHT', $prefs['edit_area.height']);
273 function setGlobalTokens () {
274 global $user, $logo, $RCS_IDS;
276 // FIXME: This a a bit of dangerous hackage.
277 $this->qreplace('BROWSE', WikiURL(''));
278 $this->qreplace('CSS_URL', DataURL(CSS_URL));
281 $this->setWikiUserTokens($user);
283 $this->qreplace('LOGO', DataURL($logo));
285 $this->qreplace('RCS_IDS', $RCS_IDS);
287 $this->qreplace('BASE_URL',
289 WikiURL($GLOBALS['pagename'], false, 'absolute_url'));
295 * Generate page contents using a template.
297 * This is a convenience function for backwards compatibility with the old
300 * @param $template string name of the template (see config.php for list of names)
302 * @param $content string html content to put into the page
304 * @param $title string page title
306 * @param $page_revision object Current WikiDB_PageRevision, if available.
308 * @return string HTML expansion of template.
310 function GeneratePage($template, $content, $title, $page_revision = false) {
311 // require_once("lib/template.php");
312 $t = new WikiTemplate($template);
314 $t->setPageRevisionTokens($page_revision);
315 $t->replace('CONTENT', $content);
316 $t->replace('TITLE', $title);
317 return $t->getExpansion();
324 // c-hanging-comment-ender-p: nil
325 // indent-tabs-mode: nil