]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/display.php
Activated Id substitution for Subversion
[SourceForge/phpwiki.git] / lib / display.php
1 <?php
2 // display.php: fetch page or get default content
3 rcs_id('$Id$');
4
5 require_once('lib/Template.php');
6
7 /**
8  * Extract keywords from Category* links on page. 
9  */
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()) {
20         $m = array();
21         if (preg_match($KeywordLinkRegexp, $link->getName(), $m))
22             $keywords[] = SplitPagename($m[0]);
23     }
24     $keywords[] = WIKI_NAME;
25     return join(', ', $keywords);
26 }
27
28 /** Make a link back to redirecting page.
29  *
30  * @param $pagename string  Name of redirecting page.
31  * @return XmlContent Link to the redirecting page.
32  */
33 function RedirectorLink($pagename) {
34     $url = WikiURL($pagename, array('redirectfrom' => ''));
35     return HTML::a(array('class' => 'redirectfrom wiki',
36                          'href' => $url),
37                    $pagename);
38 }
39
40     
41 function actionPage(&$request, $action) {
42     global $WikiTheme;
43
44     $pagename = $request->getArg('pagename');
45     $version = $request->getArg('version');
46
47     $page = $request->getPage();
48     $revision = $page->getCurrentRevision();
49
50     $dbi = $request->getDbh();
51     $actionpage = $dbi->getPage($action);
52     $actionrev = $actionpage->getCurrentRevision();
53
54     $pagetitle = HTML(fmt("%s: %s", 
55                           $actionpage->getName(),
56                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
57
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')));
64
65     $transformedContent = $actionrev->getTransformedContent();
66  
67    /* Optionally tell google (and others) not to take notice of action pages.
68       RecentChanges or AllPages might be an exception.
69    */
70     $args = array();
71     if (GOOGLE_LINKS_NOFOLLOW)
72         $args = array('ROBOTS_META' => "noindex,nofollow");
73
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.
79     */
80     $format = $request->getArg('format');
81     
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,
93                                        ));
94         $html = GeneratePageAsXML($template, $pagename, $revision /*, 
95                                   array('VALID_LINKS' => $args['VALID_LINKS'])*/);
96         header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
97         echo $html;
98     } else {
99         $pagelist = null;
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;
107                 $markup = null;
108                 // return the first found pagelist
109                 $pagelist = $loader->expandPI($cached_element->_pi, $request, 
110                                               $markup, $pagename);
111                 if (is_a($pagelist, 'PageList'))
112                     break;
113             }
114         }
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.", 
119                                       $format)
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);
124         } else {
125             foreach ($pagelist->_pages as $page) {
126                 $name = $page->getName();
127                 if ($name != $pagename and $page->exists())
128                     $args['VALID_LINKS'][] = $name;
129             }
130         }
131         if ($format == 'pdf') {
132             require_once("lib/pdf.php");
133             ConvertAndDisplayPdfPageList($request, $pagelist, $args);
134         }
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);
145             } else {
146                 require_once("lib/plugin/RecentChanges.php");
147                 $plugin = new WikiPlugin_RecentChanges();
148                 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
149             }
150         } elseif ($format == 'rdf') { // all semantic relations and attributes
151             require_once("lib/SemanticWeb.php");
152             $rdf = new RdfWriter($request, $pagelist);
153             $rdf->format();
154         } elseif ($format == 'rdfs') {
155             require_once("lib/SemanticWeb.php");
156             $rdf = new RdfsWriter($request, $pagelist);
157             $rdf->format();
158         } elseif ($format == 'owl') { // or daml?
159             require_once("lib/SemanticWeb.php");
160             $rdf = new OwlWriter($request, $pagelist);
161             $rdf->format();
162         } else {
163             if (!in_array($pagename, array(_("LinkDatabase"))))
164                 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
165                               E_USER_WARNING);
166             $template = Template('browse', array('CONTENT' => $transformedContent));
167             GeneratePage($template, $pagetitle, $revision, $args);
168         }
169     }
170     $request->checkValidators();
171     flush();
172     return '';
173 }
174
175 function displayPage(&$request, $template=false) {
176     global $WikiTheme;
177     $pagename = $request->getArg('pagename');
178     $version = $request->getArg('version');
179     $page = $request->getPage();
180     if ($version) {
181         $revision = $page->getRevision($version);
182         if (!$revision)
183             NoSuchRevision($request, $page, $version);
184         /* Tell Google (and others) to ignore old versions of pages */
185         $toks['ROBOTS_META'] = "noindex,nofollow";
186     }
187     else {
188         $revision = $page->getCurrentRevision();
189     }
190
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'
196                                               ),
197                                         $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
198         $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
199         array_shift($pages);
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;
205         }
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);
212     } else {
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');
220     }
221
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);
231     }
232
233     $request->appendValidators(array('pagerev' => $revision->getVersion(),
234                                      '%mtime' => $revision->get('mtime')));
235 /*
236     // FIXME: This is also in the template...
237     if ($request->getArg('action') != 'pdf' and !headers_sent()) {
238       // FIXME: enable MathML/SVG/... support
239       if (ENABLE_XHTML_XML
240              and (!isBrowserIE()
241                   and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
242             header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
243         else
244             header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
245     }
246 */
247
248     $toks['TITLE'] = $pagetitle;   // <title> tag
249     $toks['HEADER'] = $pageheader; // h1 with backlink
250     $toks['revision'] = $revision;
251
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.
266                 */
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);
284                 }
285             }
286         } else {
287             $page_content = $revision->getTransformedContent();
288         }
289     } else {
290         $page_content = $revision->getTransformedContent();
291     }
292    
293     /* Check for special pagenames, which are no actionpages. */
294     /*
295     if ( $pagename == _("RecentVisitors")) {
296         $toks['ROBOTS_META']="noindex,follow";
297     } else
298     */
299     if ($pagename == _("SandBox")) {
300         $toks['ROBOTS_META']="noindex,nofollow";
301     } else if (!isset($toks['ROBOTS_META'])) {
302         $toks['ROBOTS_META'] = "index,follow";
303     }
304     if (!isset($toks['CONTENT']))
305         $toks['CONTENT'] = new Template('browse', $request, $page_content);
306     if (!empty($redirect_message))
307         $toks['redirected'] = $redirect_message;
308
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);
313     if (!$template)
314         $template = new Template('html', $request);
315
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.
323      */
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);
329     } else {
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);
341             else {    
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);
346             }
347         } elseif ($format == 'rdf') { // all semantic relations and attributes
348             require_once("lib/SemanticWeb.php");
349             $rdf = new RdfWriter($request, $pagelist);
350             $rdf->format();
351         } elseif ($format == 'owl') { // or daml?
352             require_once("lib/SemanticWeb.php");
353             $rdf = new OwlWriter($request, $pagelist);
354             $rdf->format();
355         } else {
356             if (!in_array($pagename, array(_("LinkDatabase"))))
357                 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
358                               E_USER_WARNING);
359             $template->printExpansion($toks);
360         }
361     }
362     
363     $page->increaseHitCount();
364
365     if ($request->getArg('action') != 'pdf')
366         $request->checkValidators();
367     flush();
368     return '';
369 }
370
371 // $Log: not supported by cvs2svn $
372 // Revision 1.78  2008/02/14 18:48:42  rurban
373 // VALID_LINKS only for existing pages
374 //
375 // Revision 1.77  2007/09/12 19:32:29  rurban
376 // link only VALID_LINKS with pagelist HTML_DUMP
377 //
378 // Revision 1.76  2007/08/10 21:59:27  rurban
379 // fix missing PageList dependency
380 // add format=rdfs
381 //
382 // Revision 1.75  2007/07/01 09:17:45  rurban
383 // add ATOM support, a very questionable format
384 //
385 // Revision 1.74  2007/06/07 17:01:27  rurban
386 // actionPage has no toks: fix format=rss* on actionpages
387 //
388 // Revision 1.73  2007/05/30 20:43:31  rurban
389 // added MonoBook UserContribs
390 //
391 // Revision 1.72  2007/05/13 18:13:12  rurban
392 // LinkDatabase format exceptions
393 //
394 // Revision 1.71  2007/02/17 22:39:05  rurban
395 // format=rss overhaul
396 //
397 // Revision 1.70  2007/01/22 23:43:06  rurban
398 // Add RecentChanges format=sidebar
399 //
400 // Revision 1.69  2007/01/20 15:53:51  rurban
401 // Rewrite of SearchHighlight: through ActionPage and InlineParser
402 //
403 // Revision 1.68  2007/01/20 11:25:19  rurban
404 // actionPage: request is already global
405 //
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).
408 //
409 // Revision 1.66  2006/03/19 14:26:29  rurban
410 // sf.net patch by Matt Brown: Add rel=nofollow to more actions
411 //
412 // Revision 1.65  2005/05/05 08:54:40  rurban
413 // fix pagename split for title and header
414 //
415 // Revision 1.64  2005/04/23 11:21:55  rurban
416 // honor theme-specific SplitWikiWord in the HEADER
417 //
418 // Revision 1.63  2004/11/30 17:48:38  rurban
419 // just comments
420 //
421 // Revision 1.62  2004/11/30 09:51:35  rurban
422 // changed KEYWORDS from pageprefix to search term. added installer detection.
423 //
424 // Revision 1.61  2004/11/21 11:59:19  rurban
425 // remove final \n to be ob_cache independent
426 //
427 // Revision 1.60  2004/11/19 19:22:03  rurban
428 // ModeratePage part1: change status
429 //
430 // Revision 1.59  2004/11/17 20:03:58  rurban
431 // Typo: call SearchHighlight not SearchHighLight
432 //
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
443 //
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
448 // ...
449 //
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
452 //
453 // Revision 1.55  2004/09/26 14:58:35  rurban
454 // naive SearchHighLight implementation
455 //
456 // Revision 1.54  2004/09/17 14:19:41  rurban
457 // disable Content-Type header for now, until it is fixed
458 //
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
465 //
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
473 //
474 // Revision 1.51  2004/05/18 16:23:39  rurban
475 // rename split_pagename to SplitPagename
476 //
477 // Revision 1.50  2004/05/04 22:34:25  rurban
478 // more pdf support
479 //
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)
484 //
485
486 // For emacs users
487 // Local Variables:
488 // mode: php
489 // tab-width: 8
490 // c-basic-offset: 4
491 // c-hanging-comment-ender-p: nil
492 // indent-tabs-mode: nil
493 // End:
494 ?>