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',
41 function actionPage(&$request, $action) {
44 $pagename = $request->getArg('pagename');
45 $version = $request->getArg('version');
47 $page = $request->getPage();
48 $revision = $page->getCurrentRevision();
50 $dbi = $request->getDbh();
51 $actionpage = $dbi->getPage($action);
52 $actionrev = $actionpage->getCurrentRevision();
54 $pagetitle = HTML(fmt("%s: %s",
55 $actionpage->getName(),
56 $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
58 $request->setValidators(array('pageversion' => $revision->getVersion(),
59 '%mtime' => $revision->get('mtime')));
60 $request->appendValidators(array('pagerev' => $revision->getVersion(),
61 '%mtime' => $revision->get('mtime')));
62 $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
63 '%mtime' => $actionrev->get('mtime')));
65 $transformedContent = $actionrev->getTransformedContent();
67 /* Optionally tell google (and others) not to take notice of action pages.
68 RecentChanges or AllPages might be an exception.
71 if (GOOGLE_LINKS_NOFOLLOW)
72 $args = array('ROBOTS_META' => "noindex,nofollow");
74 /* Handle other formats: So far we had html only.
75 xml is requested by loaddump, rss is handled by recentchanges,
76 pdf is a special action, but should be a format to dump multiple pages
77 if the actionpage plugin returns a pagelist.
78 rdf and owl are handled by SemanticWeb.
80 $format = $request->getArg('format');
82 /* At first the single page formats: html, xml */
83 if ($pagename == _("LinkDatabase")) {
84 $template = Template('browse', array('CONTENT' => $transformedContent));
85 GeneratePage($template, $pagetitle, $revision, $args);
86 } elseif (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
87 $template = Template('browse', array('CONTENT' => $transformedContent));
88 GeneratePage($template, $pagetitle, $revision, $args);
89 } elseif ($format == 'xml') {
90 $template = new Template('browse', $request,
91 array('revision' => $revision,
92 'CONTENT' => $transformedContent,
94 $html = GeneratePageAsXML($template, $pagename, $revision /*,
95 array('VALID_LINKS' => $args['VALID_LINKS'])*/);
96 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
100 require_once('lib/WikiPlugin.php');
101 // Then the multi-page formats
102 // rss (if not already handled by RecentChanges)
103 // Need the pagelist from the first plugin
104 foreach($transformedContent->_content as $cached_element) {
105 if (is_a($cached_element, "Cached_PluginInvocation")) {
106 $loader = new WikiPluginLoader;
108 // return the first found pagelist
109 $pagelist = $loader->expandPI($cached_element->_pi, $request,
111 if (is_a($pagelist, 'PageList'))
115 $args['VALID_LINKS'] = array($pagename);
116 if (!$pagelist or !is_a($pagelist, 'PageList')) {
117 if (!in_array($format, array("rss91","rss2","rss","atom","rdf")))
118 trigger_error(sprintf("Format %s requires an actionpage returning a pagelist.",
120 ."\n".("Fall back to single page mode"), E_USER_WARNING);
121 require_once('lib/PageList.php');
122 $pagelist = new PageList();
123 $pagelist->addPage($page);
125 foreach ($pagelist->_pages as $page) {
126 $name = $page->getName();
127 if ($name != $pagename and $page->exists())
128 $args['VALID_LINKS'][] = $name;
131 if ($format == 'pdf') {
132 require_once("lib/pdf.php");
133 ConvertAndDisplayPdfPageList($request, $pagelist, $args);
135 elseif ($format == 'ziphtml') { // need to fix links
136 require_once('lib/loadsave.php');
137 $request->setArg('zipname', FilenameForPage($pagename).".zip");
138 $request->setArg('pages', $args['VALID_LINKS']);
139 MakeWikiZipHtml($request);
140 } // time-sorted RDF รก la RecentChanges
141 elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
142 $args = $request->getArgs();
143 if ($pagename == _("RecentChanges")) {
144 $template->printExpansion($args);
146 require_once("lib/plugin/RecentChanges.php");
147 $plugin = new WikiPlugin_RecentChanges();
148 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
150 } elseif ($format == 'rdf') { // all semantic relations and attributes
151 require_once("lib/SemanticWeb.php");
152 $rdf = new RdfWriter($request, $pagelist);
154 } elseif ($format == 'rdfs') {
155 require_once("lib/SemanticWeb.php");
156 $rdf = new RdfsWriter($request, $pagelist);
158 } elseif ($format == 'owl') { // or daml?
159 require_once("lib/SemanticWeb.php");
160 $rdf = new OwlWriter($request, $pagelist);
163 if (!in_array($pagename, array(_("LinkDatabase"))))
164 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
166 $template = Template('browse', array('CONTENT' => $transformedContent));
167 GeneratePage($template, $pagetitle, $revision, $args);
170 $request->checkValidators();
175 function displayPage(&$request, $template=false) {
177 $pagename = $request->getArg('pagename');
178 $version = $request->getArg('version');
179 $page = $request->getPage();
181 $revision = $page->getRevision($version);
183 NoSuchRevision($request, $page, $version);
184 /* Tell Google (and others) to ignore old versions of pages */
185 $toks['ROBOTS_META'] = "noindex,nofollow";
188 $revision = $page->getCurrentRevision();
191 if (isSubPage($pagename)) {
192 $pages = explode(SUBPAGE_SEPARATOR, $pagename);
193 $last_page = array_pop($pages); // deletes last element from array as side-effect
194 $pageheader = HTML::span(HTML::a(array('href' => WikiURL($pages[0]),
195 'class' => 'pagetitle'
197 $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
198 $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
200 foreach ($pages as $p) {
201 $pageheader->pushContent(HTML::a(array('href' => WikiURL($first_pages . $p),
202 'class' => 'backlinks'),
203 $WikiTheme->maybeSplitWikiWord($p . SUBPAGE_SEPARATOR)));
204 $first_pages .= $p . SUBPAGE_SEPARATOR;
206 $backlink = HTML::a(array('href' => WikiURL($pagename,
207 array('action' => _("BackLinks"))),
208 'class' => 'backlinks'),
209 $WikiTheme->maybeSplitWikiWord($last_page));
210 $backlink->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
211 $pageheader->pushContent($backlink);
213 $pageheader = HTML::a(array('href' => WikiURL($pagename,
214 array('action' => _("BackLinks"))),
215 'class' => 'backlinks'),
216 $WikiTheme->maybeSplitWikiWord($pagename));
217 $pageheader->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
218 if ($request->getArg('frame'))
219 $pageheader->setAttr('target', '_top');
222 $pagetitle = SplitPagename($pagename);
223 if (($redirect_from = $request->getArg('redirectfrom'))) {
224 $redirect_message = HTML::span(array('class' => 'redirectfrom'),
225 fmt("(Redirected from %s)",
226 RedirectorLink($redirect_from)));
227 // abuse the $redirected template var for some status update notice
228 } elseif ($request->getArg('errormsg')) {
229 $redirect_message = $request->getArg('errormsg');
230 $request->setArg('errormsg', false);
233 $request->appendValidators(array('pagerev' => $revision->getVersion(),
234 '%mtime' => $revision->get('mtime')));
236 // FIXME: This is also in the template...
237 if ($request->getArg('action') != 'pdf' and !headers_sent()) {
238 // FIXME: enable MathML/SVG/... support
241 and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
242 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
244 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
248 $toks['TITLE'] = $pagetitle; // <title> tag
249 $toks['HEADER'] = $pageheader; // h1 with backlink
250 $toks['revision'] = $revision;
252 // On external searchengine (google) referrer, highlight the searchterm and
253 // pass through the Searchhighlight actionpage.
254 if ($result = isExternalReferrer($request)) {
255 if (!empty($result['query'])) {
256 if (ENABLE_SEARCHHIGHLIGHT) {
257 $request->_searchhighlight = $result;
258 $request->appendValidators(array('%mtime' => time())); // force no cache(?)
259 // Should be changed to check the engine and search term only
260 // $request->setArg('nocache', 1);
261 $page_content = new TransformedText($revision->getPage(),
262 $revision->getPackedContent(),
263 $revision->getMetaData());
264 /* Now add the SearchHighlight plugin to the top of the page, in memory only.
265 You can parametrize this by changing the SearchHighlight action page.
267 if ($actionpage = $request->findActionPage('SearchHighlight')) {
268 $actionpage = $request->getPage($actionpage);
269 $actionrev = $actionpage->getCurrentRevision();
270 $pagetitle = HTML(fmt("%s: %s",
271 $actionpage->getName(),
272 $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
273 $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
274 '%mtime' => $actionrev->get('mtime')));
275 $toks['SEARCH_ENGINE'] = $result['engine'];
276 $toks['SEARCH_ENGINE_URL'] = $result['engine_url'];
277 $toks['SEARCH_TERM'] = $result['query'];
278 //$toks['HEADER'] = HTML($actionpage->getName(),": ",$pageheader); // h1 with backlink
279 $actioncontent = new TransformedText($actionrev->getPage(),
280 $actionrev->getPackedContent(),
281 $actionrev->getMetaData());
282 // prepend the actionpage in front of the hightlighted content
283 $toks['CONTENT'] = HTML($actioncontent, $page_content);
287 $page_content = $revision->getTransformedContent();
290 $page_content = $revision->getTransformedContent();
293 /* Check for special pagenames, which are no actionpages. */
295 if ( $pagename == _("RecentVisitors")) {
296 $toks['ROBOTS_META']="noindex,follow";
299 if ($pagename == _("SandBox")) {
300 $toks['ROBOTS_META']="noindex,nofollow";
301 } else if (!isset($toks['ROBOTS_META'])) {
302 $toks['ROBOTS_META'] = "index,follow";
304 if (!isset($toks['CONTENT']))
305 $toks['CONTENT'] = new Template('browse', $request, $page_content);
306 if (!empty($redirect_message))
307 $toks['redirected'] = $redirect_message;
309 // Massive performance problem parsing at run-time into all xml objects
310 // looking for p's. Should be optional, if not removed at all.
311 //$toks['PAGE_DESCRIPTION'] = $page_content->getDescription();
312 $toks['PAGE_KEYWORDS'] = GleanKeywords($page);
314 $template = new Template('html', $request);
316 // Handle other formats: So far we had html only.
317 // xml is requested by loaddump, rss is handled by RecentChanges,
318 // pdf is a special action, but should be a format to dump multiple pages
319 // if the actionpage plugin returns a pagelist.
320 // rdf, owl, kbmodel, daml, ... are handled by SemanticWeb.
321 $format = $request->getArg('format');
322 /* Only single page versions. rss only if not already handled by RecentChanges.
324 if (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
325 $template->printExpansion($toks);
326 } elseif ($format == 'xml') {
327 $template = new Template('htmldump', $request);
328 $template->printExpansion($toks);
330 // No pagelist here. Single page version only
331 require_once("lib/PageList.php");
332 $pagelist = new PageList();
333 $pagelist->addPage($page);
334 if ($format == 'pdf') {
335 require_once("lib/pdf.php");
336 ConvertAndDisplayPdfPageList($request, $pagelist);
337 // time-sorted rdf a la RecentChanges
338 } elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
339 if ($pagename == _("RecentChanges"))
340 $template->printExpansion($toks);
342 require_once("lib/plugin/RecentChanges.php");
343 $plugin = new WikiPlugin_RecentChanges();
344 $args = $request->getArgs();
345 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
347 } elseif ($format == 'rdf') { // all semantic relations and attributes
348 require_once("lib/SemanticWeb.php");
349 $rdf = new RdfWriter($request, $pagelist);
351 } elseif ($format == 'owl') { // or daml?
352 require_once("lib/SemanticWeb.php");
353 $rdf = new OwlWriter($request, $pagelist);
356 if (!in_array($pagename, array(_("LinkDatabase"))))
357 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
359 $template->printExpansion($toks);
363 $page->increaseHitCount();
365 if ($request->getArg('action') != 'pdf')
366 $request->checkValidators();
371 // $Log: not supported by cvs2svn $
372 // Revision 1.78 2008/02/14 18:48:42 rurban
373 // VALID_LINKS only for existing pages
375 // Revision 1.77 2007/09/12 19:32:29 rurban
376 // link only VALID_LINKS with pagelist HTML_DUMP
378 // Revision 1.76 2007/08/10 21:59:27 rurban
379 // fix missing PageList dependency
382 // Revision 1.75 2007/07/01 09:17:45 rurban
383 // add ATOM support, a very questionable format
385 // Revision 1.74 2007/06/07 17:01:27 rurban
386 // actionPage has no toks: fix format=rss* on actionpages
388 // Revision 1.73 2007/05/30 20:43:31 rurban
389 // added MonoBook UserContribs
391 // Revision 1.72 2007/05/13 18:13:12 rurban
392 // LinkDatabase format exceptions
394 // Revision 1.71 2007/02/17 22:39:05 rurban
395 // format=rss overhaul
397 // Revision 1.70 2007/01/22 23:43:06 rurban
398 // Add RecentChanges format=sidebar
400 // Revision 1.69 2007/01/20 15:53:51 rurban
401 // Rewrite of SearchHighlight: through ActionPage and InlineParser
403 // Revision 1.68 2007/01/20 11:25:19 rurban
404 // actionPage: request is already global
406 // Revision 1.67 2007/01/07 18:44:20 rurban
407 // Support format handlers for single- and multi-page: pagelists from actionpage plugins. Use USE_SEARCHHIGHLIGHT. Fix InlineHighlight (still experimental).
409 // Revision 1.66 2006/03/19 14:26:29 rurban
410 // sf.net patch by Matt Brown: Add rel=nofollow to more actions
412 // Revision 1.65 2005/05/05 08:54:40 rurban
413 // fix pagename split for title and header
415 // Revision 1.64 2005/04/23 11:21:55 rurban
416 // honor theme-specific SplitWikiWord in the HEADER
418 // Revision 1.63 2004/11/30 17:48:38 rurban
421 // Revision 1.62 2004/11/30 09:51:35 rurban
422 // changed KEYWORDS from pageprefix to search term. added installer detection.
424 // Revision 1.61 2004/11/21 11:59:19 rurban
425 // remove final \n to be ob_cache independent
427 // Revision 1.60 2004/11/19 19:22:03 rurban
428 // ModeratePage part1: change status
430 // Revision 1.59 2004/11/17 20:03:58 rurban
431 // Typo: call SearchHighlight not SearchHighLight
433 // Revision 1.58 2004/11/09 17:11:16 rurban
434 // * revert to the wikidb ref passing. there's no memory abuse there.
435 // * use new wikidb->_cache->_id_cache[] instead of wikidb->_iwpcache, to effectively
436 // store page ids with getPageLinks (GleanDescription) of all existing pages, which
437 // are also needed at the rendering for linkExistingWikiWord().
438 // pass options to pageiterator.
439 // use this cache also for _get_pageid()
440 // This saves about 8 SELECT count per page (num all pagelinks).
441 // * fix passing of all page fields to the pageiterator.
442 // * fix overlarge session data which got broken with the latest ACCESS_LOG_SQL changes
444 // Revision 1.57 2004/11/01 10:43:57 rurban
445 // seperate PassUser methods into seperate dir (memory usage)
446 // fix WikiUser (old) overlarge data session
447 // remove wikidb arg from various page class methods, use global ->_dbi instead
450 // Revision 1.56 2004/10/14 13:44:14 rurban
451 // fix lib/display.php:159: Warning[2]: Argument to array_reverse() should be an array
453 // Revision 1.55 2004/09/26 14:58:35 rurban
454 // naive SearchHighLight implementation
456 // Revision 1.54 2004/09/17 14:19:41 rurban
457 // disable Content-Type header for now, until it is fixed
459 // Revision 1.53 2004/06/25 14:29:20 rurban
460 // WikiGroup refactoring:
461 // global group attached to user, code for not_current user.
462 // improved helpers for special groups (avoid double invocations)
463 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
464 // fixed a XHTML validation error on userprefs.tmpl
466 // Revision 1.52 2004/06/14 11:31:37 rurban
467 // renamed global $Theme to $WikiTheme (gforge nameclash)
468 // inherit PageList default options from PageList
469 // default sortby=pagename
470 // use options in PageList_Selectable (limit, sortby, ...)
471 // added action revert, with button at action=diff
472 // added option regex to WikiAdminSearchReplace
474 // Revision 1.51 2004/05/18 16:23:39 rurban
475 // rename split_pagename to SplitPagename
477 // Revision 1.50 2004/05/04 22:34:25 rurban
480 // Revision 1.49 2004/04/18 01:11:52 rurban
481 // more numeric pagename fixes.
482 // fixed action=upload with merge conflict warnings.
483 // charset changed from constant to global (dynamic utf-8 switching)
491 // c-hanging-comment-ender-p: nil
492 // indent-tabs-mode: nil