4 * Copyright 2005,2007 $ThePhpWikiProgrammingTeam
5 * Copyright 2008-2011 Marc-Etienne Vargenau, Alcatel-Lucent
7 * This file is part of PhpWiki.
9 * PhpWiki is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * PhpWiki is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * Template: Parametrized blocks.
26 * Include text from a wiki page and replace certain placeholders by parameters.
27 * Similiar to CreatePage with the template argument, but at run-time.
28 * Similiar to the mediawiki templates but not with the "|" parameter seperator.
29 * Usage: <<Template page=TemplateFilm vars="title=rurban&year=1999" >>
31 * See also: http://meta.wikimedia.org/wiki/Help:Template
33 * Parameter expansion:
34 * vars="var1=value1&var2=value2"
35 * We only support named parameters, not numbered ones as in mediawiki, and
36 * the placeholder is %%var%% and not {{{var}}} as in mediawiki.
38 * The following predefined uppercase variables are automatically expanded if existing:
40 * MTIME - last modified date + time
41 * CTIME - creation date + time
42 * AUTHOR - last author
44 * CREATOR - first author
45 * SERVER_URL, DATA_PATH, SCRIPT_NAME, PHPWIKI_BASE_URL and BASE_URL
47 * <noinclude> .. </noinclude> is stripped from the template expansion.
48 * <includeonly> .. </includeonly> is only expanded in pages using the template,
49 * not in the template itself.
51 * We support a mediawiki-style syntax extension which maps
52 * {{TemplateFilm|title=Some Good Film|year=1999}}
54 * <<Template page=TemplateFilm vars="title=Some Good Film&year=1999" >>
57 class WikiPlugin_Template
60 function getDescription()
62 return _("Parametrized page inclusion.");
65 function getDefaultArguments()
68 'page' => false, // the page to include
69 'vars' => false, // TODO: get rid of this, all remaining args should be vars
70 'rev' => false, // the revision (defaults to most recent)
71 'section' => false, // just include a named section
72 'sectionhead' => false // when including a named section show the heading
76 function allow_undeclared_arg($name, $value)
78 // either just allow it or you can store it here away also.
79 $this->vars[$name] = $value;
80 return $name != 'action';
83 // TODO: check if page can really be pulled from the args, or if it is just the basepage.
84 function getWikiPageLinks($argstr, $basepage)
86 $args = $this->getArgs($argstr);
87 $page = isset($args['page']) ? $args['page'] : '';
89 // Expand relative page names.
90 $page = new WikiPageName($page, $basepage);
92 if (!$page or !$page->name)
96 if (empty($backlinks)) {
98 $this->run($request->_dbi, $argstr, $request, $basepage);
101 $backlinks[] = array('linkto' => $page->name, 'relation' => 0);
107 * @param string $argstr
108 * @param WikiRequest $request
109 * @param string $basepage
112 function run($dbi, $argstr, &$request, $basepage)
114 $this->vars = array();
115 $args = $this->getArgs($argstr, $request);
116 $vars = $args['vars'] ? $args['vars'] : $this->vars;
117 $page = $args['page'];
120 // Expand relative page names.
121 $page = new WikiPageName($page, $basepage);
125 return $this->error(sprintf(_("A required argument ā%sā is missing."), 'page'));
128 // If "Template:$page" exists, use it
129 // else if "Template/$page" exists, use it
131 if ($dbi->isWikiPage("Template:" . $page)) {
132 $page = "Template:" . $page;
133 } elseif ($dbi->isWikiPage("Template/" . $page)) {
134 $page = "Template/" . $page;
137 // Protect from recursive inclusion.
139 if ($rootpage == '') {
140 $rootpage = $basepage;
142 if ($page == $rootpage) {
143 return $this->error(sprintf(_("Recursive inclusion of page %s ignored"),
147 // Check if page exists
148 if (!($dbi->isWikiPage($page))) {
149 return $this->error(sprintf(_("Page ā%sā does not exist."), $page));
152 // Check if user is allowed to get the Page.
153 if (!mayAccessPage('view', $page)) {
154 return $this->error(sprintf(_("Illegal inclusion of page %s: no read access."),
158 $p = $dbi->getPage($page);
160 if (!is_whole_number($args['rev']) or !($args['rev'] > 0)) {
161 return $this->error(_("Error: rev must be a positive integer."));
163 $r = $p->getRevision($args['rev']);
164 if ((!$r) || ($r->hasDefaultContents())) {
165 return $this->error(sprintf(_("%s: no such revision %d."),
166 $page, $args['rev']));
169 $r = $p->getCurrentRevision();
171 $initial_content = $r->getPackedContent();
173 $content = $r->getContent();
175 if ((preg_match('/<' . '\?plugin\s+RedirectTo\s+page=(\S+)\s*\?' . '>/', implode("\n", $content), $m))
176 or (preg_match('/<' . '\?plugin\s+RedirectTo\s+page=(.*?)\s*\?' . '>/', implode("\n", $content), $m))
177 or (preg_match('/<<\s*RedirectTo\s+page=(\S+)\s*>>/', implode("\n", $content), $m))
178 or (preg_match('/<<\s*RedirectTo\s+page="(.*?)"\s*>>/', implode("\n", $content), $m))
180 // Strip quotes (simple or double) from page name if any
181 if ((string_starts_with($m[1], "'"))
182 or (string_starts_with($m[1], "\""))
184 $m[1] = substr($m[1], 1, -1);
186 // trap recursive redirects
187 if ($m[1] == $rootpage) {
188 return $this->error(sprintf(_("Recursive inclusion of page %s ignored"),
189 $page . ' => ' . $m[1]));
192 $p = $dbi->getPage($page);
193 $r = $p->getCurrentRevision();
194 $initial_content = $r->getPackedContent();
197 if ($args['section']) {
198 $c = explode("\n", $initial_content);
199 $c = extractSection($args['section'], $c, $page, $quiet, $args['sectionhead']);
200 $initial_content = implode("\n", $c);
202 // exclude from expansion
203 if (preg_match('/<noinclude>.+<\/noinclude>/s', $initial_content)) {
204 $initial_content = preg_replace("/<noinclude>.+?<\/noinclude>/s", "",
208 $initial_content = preg_replace("/<includeonly>(.+)<\/includeonly>/s", "\\1",
210 $this->doVariableExpansion($initial_content, $vars, $basepage, $request);
212 // If content is single-line, call TransformInline, else call TransformText
213 $initial_content = trim($initial_content, "\n");
214 if (preg_match("/\n/", $initial_content)) {
215 include_once 'lib/BlockParser.php';
216 $content = TransformText($initial_content, $page);
218 include_once 'lib/InlineParser.php';
219 $content = TransformInline($initial_content, $page);
226 * Expand template variables. Used by the TemplatePlugin and the CreatePagePlugin
228 function doVariableExpansion(&$content, $vars, $basepage, &$request)
230 if (preg_match('/%%\w+%%/', $content)) // need variable expansion
232 $dbi =& $request->_dbi;
234 if (is_string($vars) and !empty($vars)) {
235 foreach (explode("&", $vars) as $pair) {
236 list($key, $val) = explode("=", $pair);
239 } elseif (is_array($vars)) {
242 $thispage = $dbi->getPage($basepage);
243 // pagename and userid are not overridable
244 $var['PAGENAME'] = $thispage->getName();
245 if (preg_match('/%%USERID%%/', $content))
246 $var['USERID'] = $request->_user->getId();
247 if (empty($var['MTIME']) and preg_match('/%%MTIME%%/', $content)) {
248 $thisrev = $thispage->getCurrentRevision(false);
249 $var['MTIME'] = $GLOBALS['WikiTheme']->formatDateTime($thisrev->get('mtime'));
251 if (empty($var['CTIME']) and preg_match('/%%CTIME%%/', $content)) {
252 if ($first = $thispage->getRevision(1, false))
253 $var['CTIME'] = $GLOBALS['WikiTheme']->formatDateTime($first->get('mtime'));
255 if (empty($var['AUTHOR']) and preg_match('/%%AUTHOR%%/', $content))
256 $var['AUTHOR'] = $thispage->getAuthor();
257 if (empty($var['OWNER']) and preg_match('/%%OWNER%%/', $content))
258 $var['OWNER'] = $thispage->getOwner();
259 if (empty($var['CREATOR']) and preg_match('/%%CREATOR%%/', $content))
260 $var['CREATOR'] = $thispage->getCreator();
261 foreach (array("SERVER_URL", "DATA_PATH", "SCRIPT_NAME", "PHPWIKI_BASE_URL") as $c) {
262 // constants are not overridable
263 if (preg_match('/%%' . $c . '%%/', $content))
264 $var[$c] = constant($c);
266 if (preg_match('/%%BASE_URL%%/', $content))
267 $var['BASE_URL'] = PHPWIKI_BASE_URL;
269 foreach ($var as $key => $val) {
270 // We have to decode the double quotes that have been encoded
271 // in inline or block parser.
272 $content = str_replace("%%" . $key . "%%", htmlspecialchars_decode($val), $content);
283 // c-hanging-comment-ender-p: nil
284 // indent-tabs-mode: nil