2 // display.php: fetch page or get default content
5 require_once('lib/Template.php');
8 * Extract keywords from Category* links on page.
10 function GleanKeywords ($page) {
11 if (!defined('KEYWORDS')) return '';
12 require_once("lib/TextSearchQuery.php");
13 $search = new TextSearchQuery(KEYWORDS, true);
14 $KeywordLinkRegexp = $search->asRegexp();
15 // iterate over the pagelinks (could be a large number) [15ms on PluginManager]
16 // or do a titleSearch and check the categories if they are linked?
17 $links = $page->getPageLinks();
18 $keywords[] = SplitPagename($page->getName());
19 while ($link = $links->next()) {
21 if (preg_match($KeywordLinkRegexp, $link->getName(), $m))
22 $keywords[] = SplitPagename($m[0]);
24 $keywords[] = WIKI_NAME;
25 return join(', ', $keywords);
28 /** Make a link back to redirecting page.
30 * @param $pagename string Name of redirecting page.
31 * @return XmlContent Link to the redirecting page.
33 function RedirectorLink($pagename) {
34 $url = WikiURL($pagename, array('redirectfrom' => ''));
35 return HTML::a(array('class' => 'redirectfrom wiki',
40 /* only on ?action= */
41 function actionPage(&$request, $action) {
45 $pagename = $request->getArg('pagename');
46 $version = $request->getArg('version');
48 $page = $request->getPage();
49 $revision = $page->getCurrentRevision();
51 $dbi = $request->getDbh();
52 $actionpage = $dbi->getPage($action);
53 $actionrev = $actionpage->getCurrentRevision();
55 $pagetitle = HTML(fmt("%s: %s",
56 $actionpage->getName(),
57 $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
59 $request->setValidators(array('pageversion' => $revision->getVersion(),
60 '%mtime' => $revision->get('mtime')));
61 $request->appendValidators(array('pagerev' => $revision->getVersion(),
62 '%mtime' => $revision->get('mtime')));
63 $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
64 '%mtime' => $actionrev->get('mtime')));
66 $transformedContent = $actionrev->getTransformedContent();
68 /* Optionally tell google (and others) not to take notice of action pages.
69 RecentChanges or AllPages might be an exception.
72 if (GOOGLE_LINKS_NOFOLLOW) {
73 $robots = "noindex,nofollow";
74 $args = array('ROBOTS_META' => $robots);
77 /* Handle other formats: So far we had html only.
78 xml is requested by loaddump, rss is handled by recentchanges,
79 pdf is a special action, but should be a format to dump multiple pages
80 if the actionpage plugin returns a pagelist.
81 rdf and owl are handled by SemanticWeb.
83 $format = $request->getArg('format');
85 /* At first the single page formats: html, xml */
86 if ($pagename == _("LinkDatabase")) {
87 $template = Template('browse', array('CONTENT' => $transformedContent));
88 GeneratePage($template, $pagetitle, $revision, $args);
89 } elseif (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
90 $template = Template('browse', array('CONTENT' => $transformedContent));
91 GeneratePage($template, $pagetitle, $revision, $args);
92 } elseif ($format == 'xml') {
93 $request->setArg('format','');
94 $template = new Template('browse', $request,
95 array('revision' => $revision,
96 'CONTENT' => $transformedContent,
98 $html = GeneratePageAsXML($template, $pagename, $revision /*,
99 array('VALID_LINKS' => $args['VALID_LINKS'])*/);
100 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
104 require_once('lib/WikiPlugin.php');
105 // Then the multi-page formats
106 // rss (if not already handled by RecentChanges)
107 // Need the pagelist from the first plugin
108 foreach($transformedContent->_content as $cached_element) {
109 if (is_a($cached_element, "Cached_PluginInvocation")) {
110 $loader = new WikiPluginLoader;
112 // return the first found pagelist
113 $pagelist = $loader->expandPI($cached_element->_pi, $request,
115 if (is_a($pagelist, 'PageList'))
119 if (!$pagelist or !is_a($pagelist, 'PageList')) {
120 if (!in_array($format, array("rss91","rss2","rss","atom","rdf")))
121 trigger_error(sprintf("Format %s requires an actionpage returning a pagelist.",
123 ."\n".("Fall back to single page mode"), E_USER_WARNING);
124 require_once('lib/PageList.php');
125 $pagelist = new PageList();
126 if ($format == 'pdf')
127 $pagelist->addPage($page);
129 foreach ($pagelist->_pages as $page) {
130 $name = $page->getName();
131 if ($name != $pagename and $page->exists())
132 $args['VALID_LINKS'][] = $name;
135 if ($format == 'pdf') {
136 require_once("lib/pdf.php");
137 array_unshift($args['VALID_LINKS'], $pagename);
138 ConvertAndDisplayPdfPageList($request, $pagelist, $args);
140 elseif ($format == 'ziphtml') { // need to fix links
141 require_once('lib/loadsave.php');
142 array_unshift($args['VALID_LINKS'], $pagename);
143 $request->setArg('zipname', FilenameForPage($pagename).".zip");
144 $request->setArg('pages', $args['VALID_LINKS']);
145 $request->setArg('format','');
146 MakeWikiZipHtml($request);
147 } // time-sorted RDF รก la RecentChanges
148 elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
149 $args = $request->getArgs();
150 //$request->setArg('format','');
151 if ($pagename == _("RecentChanges")) {
152 $template->printExpansion($args);
154 require_once("lib/plugin/RecentChanges.php");
155 $plugin = new WikiPlugin_RecentChanges();
156 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
158 } elseif ($format == 'json') { // for faster autocompletion on searches
159 $req_args =& $request->args;
160 unset($req_args['format']);
161 $json = array('count' => count($pagelist->_pages),
162 'list' => $args['VALID_LINKS'],
164 'phpwiki-version' => PHPWIKI_VERSION);
165 if (loadPhpExtension('json')) {
166 $json_enc = json_encode($json);
168 require_once("lib/pear/JSON.php");
169 $j = new Services_JSON();
170 $json_enc = $j->encode($json);
172 header("Content-Type: application/json");
174 } elseif ($format == 'rdf') { // all semantic relations and attributes
175 require_once("lib/SemanticWeb.php");
176 $rdf = new RdfWriter($request, $pagelist);
178 } elseif ($format == 'rdfs') {
179 require_once("lib/SemanticWeb.php");
180 $rdf = new RdfsWriter($request, $pagelist);
182 } elseif ($format == 'owl') { // or daml?
183 require_once("lib/SemanticWeb.php");
184 $rdf = new OwlWriter($request, $pagelist);
187 if (!in_array($pagename, array(_("LinkDatabase"))))
188 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
190 $template = Template('browse', array('CONTENT' => $transformedContent));
191 GeneratePage($template, $pagetitle, $revision, $args);
194 $request->checkValidators();
199 function displayPage(&$request, $template=false) {
202 $pagename = $request->getArg('pagename');
203 $version = $request->getArg('version');
204 $page = $request->getPage();
206 $revision = $page->getRevision($version);
208 NoSuchRevision($request, $page, $version);
209 /* Tell Google (and others) to ignore old versions of pages */
210 $robots = "noindex,nofollow";
211 $toks['ROBOTS_META'] = $robots;
214 $revision = $page->getCurrentRevision();
216 $format = $request->getArg('format');
217 if ($format == 'xml') { // fast ajax: include page content asynchronously
219 header("Content-Type: text/xml");
220 echo "<","?xml version=\"1.0\" encoding=\"$charset\"?", ">\n";
221 // DOCTYPE html needed to allow unencoded entities like without !CDATA[]
222 echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
223 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',"\n";
224 if ($page->exists()) {
225 header("Last-Modified: " . Rfc1123DateTime($revision->get('mtime')));
226 $request->cacheControl();
227 $request->setArg('format','');
228 $page_content = $revision->getTransformedContent();
229 $page_content->printXML();
230 $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
234 $request->cacheControl();
235 echo('<div style="display:none;" />');
236 $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
242 if (isSubPage($pagename)) {
243 $pages = explode(SUBPAGE_SEPARATOR, $pagename);
244 $last_page = array_pop($pages); // deletes last element from array as side-effect
245 $pageheader = HTML::span(HTML::a(array('href' => WikiURL($pages[0]),
246 'class' => 'pagetitle'
248 $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
249 $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
251 foreach ($pages as $p) {
252 $pageheader->pushContent(HTML::a(array('href' => WikiURL($first_pages . $p),
253 'class' => 'backlinks'),
254 $WikiTheme->maybeSplitWikiWord($p . SUBPAGE_SEPARATOR)));
255 $first_pages .= $p . SUBPAGE_SEPARATOR;
257 $backlink = HTML::a(array('href' => WikiURL($pagename,
258 array('action' => _("BackLinks"))),
259 'class' => 'backlinks'),
260 $WikiTheme->maybeSplitWikiWord($last_page));
261 $backlink->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
262 $pageheader->pushContent($backlink);
264 $pageheader = HTML::a(array('href' => WikiURL($pagename,
265 array('action' => _("BackLinks"))),
266 'class' => 'backlinks'),
267 $WikiTheme->maybeSplitWikiWord($pagename));
268 $pageheader->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
269 if ($request->getArg('frame'))
270 $pageheader->setAttr('target', '_top');
273 $pagetitle = SplitPagename($pagename);
274 if (($redirect_from = $request->getArg('redirectfrom'))) {
275 $redirect_message = HTML::span(array('class' => 'redirectfrom'),
276 fmt("(Redirected from %s)",
277 RedirectorLink($redirect_from)));
278 // abuse the $redirected template var for some status update notice
279 } elseif ($request->getArg('errormsg')) {
280 $redirect_message = $request->getArg('errormsg');
281 $request->setArg('errormsg', false);
284 $request->appendValidators(array('pagerev' => $revision->getVersion(),
285 '%mtime' => $revision->get('mtime')));
287 // FIXME: This is also in the template...
288 if ($request->getArg('action') != 'pdf' and !headers_sent()) {
289 // FIXME: enable MathML/SVG/... support
292 and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
293 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
295 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
299 $toks['TITLE'] = $pagetitle; // <title> tag
300 $toks['HEADER'] = $pageheader; // h1 with backlink
301 $toks['revision'] = $revision;
303 // On external searchengine (google) referrer, highlight the searchterm and
304 // pass through the Searchhighlight actionpage.
305 if ($result = isExternalReferrer($request)) {
306 if (!empty($result['query'])) {
307 if (ENABLE_SEARCHHIGHLIGHT) {
308 $request->_searchhighlight = $result;
309 $request->appendValidators(array('%mtime' => time())); // force no cache(?)
310 // Should be changed to check the engine and search term only
311 // $request->setArg('nocache', 1);
312 $page_content = new TransformedText($revision->getPage(),
313 $revision->getPackedContent(),
314 $revision->getMetaData());
315 /* Now add the SearchHighlight plugin to the top of the page, in memory only.
316 You can parametrize this by changing the SearchHighlight action page.
318 if ($actionpage = $request->findActionPage('SearchHighlight')) {
319 $actionpage = $request->getPage($actionpage);
320 $actionrev = $actionpage->getCurrentRevision();
321 $pagetitle = HTML(fmt("%s: %s",
322 $actionpage->getName(),
323 $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
324 $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
325 '%mtime' => $actionrev->get('mtime')));
326 $toks['SEARCH_ENGINE'] = $result['engine'];
327 $toks['SEARCH_ENGINE_URL'] = $result['engine_url'];
328 $toks['SEARCH_TERM'] = $result['query'];
329 //$toks['HEADER'] = HTML($actionpage->getName(),": ",$pageheader); // h1 with backlink
330 $actioncontent = new TransformedText($actionrev->getPage(),
331 $actionrev->getPackedContent(),
332 $actionrev->getMetaData());
333 // prepend the actionpage in front of the hightlighted content
334 $toks['CONTENT'] = HTML($actioncontent, $page_content);
338 $page_content = $revision->getTransformedContent();
341 $page_content = $revision->getTransformedContent();
344 /* Check for special pagenames, which are no actionpages. */
346 if ( $pagename == _("RecentVisitors")) {
347 $robots = "noindex,follow";
348 $toks['ROBOTS_META'] = $robots;
351 if ($pagename == _("SandBox")) {
352 $robots = "noindex,nofollow";
353 $toks['ROBOTS_META'] = $robots;
354 } else if (isActionPage($pagename)) {
355 // AllPages must not be indexed, but must be followed to get all pages
356 $robots = "noindex,follow";
357 $toks['ROBOTS_META'] = $robots;
358 } else if (!isset($toks['ROBOTS_META'])) {
359 $robots = "index,follow";
360 $toks['ROBOTS_META'] = $robots;
362 if (!isset($toks['CONTENT']))
363 $toks['CONTENT'] = new Template('browse', $request, $page_content);
364 if (!empty($redirect_message))
365 $toks['redirected'] = $redirect_message;
367 // Massive performance problem parsing at run-time into all xml objects
368 // looking for p's. Should be optional, if not removed at all.
369 //$toks['PAGE_DESCRIPTION'] = $page_content->getDescription();
370 $toks['PAGE_KEYWORDS'] = GleanKeywords($page);
372 $template = new Template('html', $request);
374 // Handle other formats: So far we had html only.
375 // xml is requested by loaddump, rss is handled by RecentChanges,
376 // pdf is a special action, but should be a format to dump multiple pages
377 // if the actionpage plugin returns a pagelist.
378 // rdf, owl, kbmodel, daml, ... are handled by SemanticWeb.
379 /* Only single page versions. rss only if not already handled by RecentChanges.
381 if (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
382 $template->printExpansion($toks);
384 // No pagelist here. Single page version only
385 require_once("lib/PageList.php");
386 $pagelist = new PageList();
387 $pagelist->addPage($page);
388 if ($format == 'pdf') {
389 require_once("lib/pdf.php");
390 $request->setArg('format','');
391 ConvertAndDisplayPdfPageList($request, $pagelist);
392 // time-sorted rdf a la RecentChanges
393 } elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
394 //$request->setArg('format','');
395 if ($pagename == _("RecentChanges"))
396 $template->printExpansion($toks);
398 require_once("lib/plugin/RecentChanges.php");
399 $plugin = new WikiPlugin_RecentChanges();
400 $args = $request->getArgs();
401 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
403 } elseif ($format == 'rdf') { // all semantic relations and attributes
404 require_once("lib/SemanticWeb.php");
405 $rdf = new RdfWriter($request, $pagelist);
407 } elseif ($format == 'owl') { // or daml?
408 require_once("lib/SemanticWeb.php");
409 $rdf = new OwlWriter($request, $pagelist);
411 } elseif ($format == 'json') { // include page content asynchronously
412 $request->setArg('format','');
414 $content = $page_content->asXML();
417 $req_args = $request->args;
418 unset($req_args['format']);
419 // no meta-data so far, just the content
420 $json = array('content' => $content,
422 'phpwiki-version' => PHPWIKI_VERSION);
423 if (loadPhpExtension('json')) {
424 $json_enc = json_encode($json);
426 require_once("lib/pear/JSON.php");
427 $j = new Services_JSON();
428 $json_enc = $j->encode($json);
430 header("Content-Type: application/json");
433 if (!in_array($pagename, array(_("LinkDatabase"))))
434 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
436 $template->printExpansion($toks);
440 $page->increaseHitCount();
442 if ($request->getArg('action') != 'pdf') {
443 $request->checkValidators();
454 // c-hanging-comment-ender-p: nil
455 // indent-tabs-mode: nil