]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/display.php
Add RecentChanges format=sidebar
[SourceForge/phpwiki.git] / lib / display.php
1 <?php
2 // display.php: fetch page or get default content
3 rcs_id('$Id: display.php,v 1.70 2007-01-22 23:43:06 rurban Exp $');
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     include_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         if (preg_match($KeywordLinkRegexp, $link->getName(), $m))
21             $keywords[] = SplitPagename($m[0]);
22     }
23     $keywords[] = WIKI_NAME;
24     return join(', ', $keywords);
25 }
26
27 /** Make a link back to redirecting page.
28  *
29  * @param $pagename string  Name of redirecting page.
30  * @return XmlContent Link to the redirecting page.
31  */
32 function RedirectorLink($pagename) {
33     $url = WikiURL($pagename, array('redirectfrom' => ''));
34     return HTML::a(array('class' => 'redirectfrom wiki',
35                          'href' => $url),
36                    $pagename);
37 }
38
39     
40 function actionPage(&$request, $action) {
41     global $WikiTheme;
42
43     $pagename = $request->getArg('pagename');
44     $version = $request->getArg('version');
45
46     $page = $request->getPage();
47     $revision = $page->getCurrentRevision();
48
49     $dbi = $request->getDbh();
50     $actionpage = $dbi->getPage($action);
51     $actionrev = $actionpage->getCurrentRevision();
52
53     $pagetitle = HTML(fmt("%s: %s", 
54                           $actionpage->getName(),
55                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
56
57     $validators = new HTTP_ValidatorSet(array('pageversion' => $revision->getVersion(),
58                                               '%mtime' => $revision->get('mtime')));
59                                         
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     /* At first the single page formats: html, xml */
82     if (!$format or $format == 'html' or $format == 'sidebar') {
83         $template = Template('browse', array('CONTENT' => $transformedContent));
84         GeneratePage($template, $pagetitle, $revision, $args);
85     } elseif ($format == 'xml') {
86         $template = Template('browse', array('CONTENT' => $transformedContent));
87         GeneratePageAsXML($template, $pagetitle, $revision, $args);
88     } else {
89         $pagelist = null;
90         // Then the multi-page formats
91         // rss (if not already handled by RecentChanges)
92         // Need the pagelist from the first plugin
93         foreach($transformedContent->_content as $cached_element) {
94             if (is_a($cached_element, "Cached_PluginInvocation")) {
95                 include_once('lib/WikiPlugin.php');
96                 $loader = new WikiPluginLoader;
97                 $markup = null;
98                 // return the first found pagelist
99                 $pagelist = $loader->expandPI($cached_element->_pi, $request, $markup, $pagename);
100                 if (is_a($pagelist, 'PageList'))
101                     break;
102             }
103         }
104         if (!$pagelist or !is_a($pagelist, 'PageList')) {
105             if (!in_array($format, array("atom","rss","rdf")))
106                 trigger_error(sprintf("Format %s requires an actionpage returning a pagelist.", $format)
107                               ."\n".("Fall back to single page mode"), E_USER_WARNING);
108             $pagelist = new PageList();
109             $pagelist->addPage($page);
110         }
111         if ($format == 'pdf') {
112             include_once("lib/pdf.php");
113             ConvertAndDisplayPdfPageList($request, $pagelist);
114         } elseif ($format == 'rss') {
115             include_once("lib/plugin/RecentChanges.php");
116             $rdf = new RssWriter($request, $pagelist);
117             $rdf->format();
118         } elseif ($format == 'rss91') {
119             include_once("lib/plugin/RecentChanges.php");
120             $rdf = new RSS91Writer($request, $pagelist);
121             $rdf->format();
122         } elseif ($format == 'rss2') {
123             include_once("lib/RssWriter2.php");
124             $rdf = new RssWriter2($request, $pagelist);
125             $rdf->format();
126         } elseif ($format == 'atom') {
127             include_once("lib/plugin/RssWriter.php");
128             $rdf = new AtomWriter($request, $pagelist);
129             $rdf->format();
130         } elseif ($format == 'rdf') { // all semantic relations and attributes
131             include_once("lib/SemanticWeb.php");
132             $rdf = new RdfWriter($request, $pagelist);
133             $rdf->format();
134         } elseif ($format == 'owl') {
135             include_once("lib/SemanticWeb.php");
136             $rdf = new OwlWriter($request, $pagelist);
137             $rdf->format();
138         } elseif ($format == 'kbmodel') {
139             include_once("lib/SemanticWeb.php");
140             $model = new ModelWriter($request, $pagelist);
141             $model->format();
142         } else {
143             trigger_error(sprintf("Unhandled format %s. Reverting to html", $format), E_USER_WARNING);
144             $template = Template('browse', array('CONTENT' => $transformedContent));
145             GeneratePage($template, $pagetitle, $revision, $args);
146         }
147     }
148     $request->checkValidators();
149     flush();
150 }
151
152 function displayPage(&$request, $template=false) {
153     global $WikiTheme;
154     $pagename = $request->getArg('pagename');
155     $version = $request->getArg('version');
156     $page = $request->getPage();
157     if ($version) {
158         $revision = $page->getRevision($version);
159         if (!$revision)
160             NoSuchRevision($request, $page, $version);
161         /* Tell Google (and others) to ignore old versions of pages */
162         $toks['ROBOTS_META'] = "noindex,nofollow";
163     }
164     else {
165         $revision = $page->getCurrentRevision();
166     }
167
168     if (isSubPage($pagename)) {
169         $pages = explode(SUBPAGE_SEPARATOR, $pagename);
170         $last_page = array_pop($pages); // deletes last element from array as side-effect
171         $pageheader = HTML::span(HTML::a(array('href' => WikiURL($pages[0]),
172                                               'class' => 'pagetitle'
173                                               ),
174                                         $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
175         $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
176         array_shift($pages);
177         foreach ($pages as $p)  {
178             $pageheader->pushContent(HTML::a(array('href' => WikiURL($first_pages . $p),
179                                                   'class' => 'backlinks'),
180                                             $WikiTheme->maybeSplitWikiWord($p . SUBPAGE_SEPARATOR)));
181             $first_pages .= $p . SUBPAGE_SEPARATOR;
182         }
183         $backlink = HTML::a(array('href' => WikiURL($pagename,
184                                                     array('action' => _("BackLinks"))),
185                                   'class' => 'backlinks'),
186                             $WikiTheme->maybeSplitWikiWord($last_page));
187         $backlink->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
188         $pageheader->pushContent($backlink);
189     } else {
190         $pageheader = HTML::a(array('href' => WikiURL($pagename,
191                                                      array('action' => _("BackLinks"))),
192                                    'class' => 'backlinks'),
193                              $WikiTheme->maybeSplitWikiWord($pagename));
194         $pageheader->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
195         if ($request->getArg('frame'))
196             $pageheader->setAttr('target', '_top');
197     }
198
199     $pagetitle = SplitPagename($pagename);
200     if (($redirect_from = $request->getArg('redirectfrom'))) {
201         $redirect_message = HTML::span(array('class' => 'redirectfrom'),
202                                        fmt("(Redirected from %s)",
203                                            RedirectorLink($redirect_from)));
204     // abuse the $redirected template var for some status update notice                                       
205     } elseif ($request->getArg('errormsg')) { 
206         $redirect_message = $request->getArg('errormsg');
207         $request->setArg('errormsg', false);
208     }
209
210     $request->appendValidators(array('pagerev' => $revision->getVersion(),
211                                      '%mtime' => $revision->get('mtime')));
212 /*
213     // FIXME: This is also in the template...
214     if ($request->getArg('action') != 'pdf' and !headers_sent()) {
215       // FIXME: enable MathML/SVG/... support
216       if (ENABLE_XHTML_XML
217              and (!isBrowserIE()
218                   and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
219             header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
220         else
221             header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
222     }
223 */
224
225     $toks['TITLE'] = $pagetitle;   // <title> tag
226     $toks['HEADER'] = $pageheader; // h1 with backlink
227     $toks['revision'] = $revision;
228
229     // On external searchengine (google) referrer, highlight the searchterm and 
230     // pass through the Searchhighlight actionpage.
231     if ($result = isExternalReferrer($request)) {
232         if (!empty($result['query'])) {
233             if (ENABLE_SEARCHHIGHLIGHT) {
234                 $request->_searchhighlight = $result;
235                 $request->appendValidators(array('%mtime' => time())); // force no cache(?)
236                 // Should be changed to check the engine and search term only
237                 // $request->setArg('nocache', 1); 
238                 $page_content = new TransformedText($revision->getPage(),
239                                                     $revision->getPackedContent(),
240                                                     $revision->getMetaData());
241                 /* Now add the SearchHighlight plugin to the top of the page, in memory only.
242                    You can parametrize this by changing the SearchHighlight action page.
243                 */
244                 if ($actionpage = $request->findActionPage('SearchHighlight')) {
245                     $actionpage = $request->getPage($actionpage);
246                     $actionrev = $actionpage->getCurrentRevision();
247                     $pagetitle = HTML(fmt("%s: %s", 
248                                           $actionpage->getName(),
249                                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
250                     $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
251                                                      '%mtime' => $actionrev->get('mtime')));
252                     $toks['SEARCH_ENGINE'] = $result['engine'];
253                     $toks['SEARCH_ENGINE_URL'] = $result['engine_url'];
254                     $toks['SEARCH_TERM'] = $result['query'];
255                     //$toks['HEADER'] = HTML($actionpage->getName(),": ",$pageheader); // h1 with backlink
256                     $actioncontent = new TransformedText($actionrev->getPage(),
257                                                          $actionrev->getPackedContent(),
258                                                          $actionrev->getMetaData());
259                     // prepend the actionpage in front of the hightlighted content
260                     $toks['CONTENT'] = HTML($actioncontent, $page_content);
261                 }
262             }
263         } else {
264             $page_content = $revision->getTransformedContent();
265         }
266     } else {
267         $page_content = $revision->getTransformedContent();
268     }
269    
270     /* Check for special pagenames, which are no actionpages. */
271     /*
272     if ( $pagename == _("RecentVisitors")) {
273         $toks['ROBOTS_META']="noindex,follow";
274     } else
275     */
276     if ($pagename == _("SandBox")) {
277         $toks['ROBOTS_META']="noindex,nofollow";
278     } else if (!isset($toks['ROBOTS_META'])) {
279         $toks['ROBOTS_META'] = "index,follow";
280     }
281     if (!isset($toks['CONTENT']))
282         $toks['CONTENT'] = new Template('browse', $request, $page_content);
283     if (!empty($redirect_message))
284         $toks['redirected'] = $redirect_message;
285     
286     $toks['PAGE_DESCRIPTION'] = $page_content->getDescription();
287     $toks['PAGE_KEYWORDS'] = GleanKeywords($page);
288     if (!$template)
289         $template = new Template('html', $request);
290
291     // Handle other formats: So far we had html only.
292     // xml is requested by loaddump, rss is handled by RecentChanges, 
293     // pdf is a special action, but should be a format to dump multiple pages
294     // if the actionpage plugin returns a pagelist.
295     // rdf, owl, kbmodel, daml, ... are handled by SemanticWeb.
296     $format = $request->getArg('format');
297     /* Only single page versions. rss only if not already handled by RecentChanges.
298      */
299     if (!$format or $format == 'html' or $format == 'sidebar') {
300         $template->printExpansion($toks);
301     } elseif ($format == 'xml') {
302         $template = new Template('htmldump', $request);
303         $template->printExpansion($toks);
304     } else {
305         // No pagelist here. Single page version only
306         include_once("lib/PageList.php");
307         $pagelist = new PageList();
308         $pagelist->addPage($page);
309         if ($format == 'pdf') {
310             include_once("lib/pdf.php");
311             ConvertAndDisplayPdfPageList($request, $pagelist);
312         } elseif ($format == 'rss') {
313             include_once("lib/plugin/RecentChanges.php");
314             $rdf = new RssWriter($request, $pagelist);
315             $rdf->format();
316         } elseif ($format == 'rss91') {
317             include_once("lib/plugin/RecentChanges.php");
318             $rdf = new RSS91Writer($request, $pagelist);
319             $rdf->format();
320         } elseif ($format == 'rss2') {
321             include_once("lib/RssWriter2.php");
322             $rdf = new RssWriter2($request, $pagelist);
323             $rdf->format();
324         } elseif ($format == 'atom') {
325             include_once("lib/plugin/RssWriter.php");
326             $rdf = new AtomWriter($request, $pagelist);
327             $rdf->format();
328         } elseif ($format == 'rdf') { // all semantic relations and attributes
329             include_once("lib/SemanticWeb.php");
330             $rdf = new RdfWriter($request, $pagelist);
331             $rdf->format();
332         } elseif ($format == 'owl') {
333             include_once("lib/SemanticWeb.php");
334             $rdf = new OwlWriter($request, $pagelist);
335             $rdf->format();
336         } elseif ($format == 'kbmodel') {
337             include_once("lib/SemanticWeb.php");
338             $model = new ModelWriter($request, $pagelist);
339             $model->format();
340         } else {
341             trigger_error(sprintf("Unhandled format %s. Reverting to html", $format), E_USER_WARNING);
342             $template->printExpansion($toks);
343         }
344     }
345     
346     $page->increaseHitCount();
347
348     if ($request->getArg('action') != 'pdf')
349         $request->checkValidators();
350     flush();
351 }
352
353 // $Log: not supported by cvs2svn $
354 // Revision 1.69  2007/01/20 15:53:51  rurban
355 // Rewrite of SearchHighlight: through ActionPage and InlineParser
356 //
357 // Revision 1.68  2007/01/20 11:25:19  rurban
358 // actionPage: request is already global
359 //
360 // Revision 1.67  2007/01/07 18:44:20  rurban
361 // Support format handlers for single- and multi-page: pagelists from actionpage plugins. Use USE_SEARCHHIGHLIGHT. Fix InlineHighlight (still experimental).
362 //
363 // Revision 1.66  2006/03/19 14:26:29  rurban
364 // sf.net patch by Matt Brown: Add rel=nofollow to more actions
365 //
366 // Revision 1.65  2005/05/05 08:54:40  rurban
367 // fix pagename split for title and header
368 //
369 // Revision 1.64  2005/04/23 11:21:55  rurban
370 // honor theme-specific SplitWikiWord in the HEADER
371 //
372 // Revision 1.63  2004/11/30 17:48:38  rurban
373 // just comments
374 //
375 // Revision 1.62  2004/11/30 09:51:35  rurban
376 // changed KEYWORDS from pageprefix to search term. added installer detection.
377 //
378 // Revision 1.61  2004/11/21 11:59:19  rurban
379 // remove final \n to be ob_cache independent
380 //
381 // Revision 1.60  2004/11/19 19:22:03  rurban
382 // ModeratePage part1: change status
383 //
384 // Revision 1.59  2004/11/17 20:03:58  rurban
385 // Typo: call SearchHighlight not SearchHighLight
386 //
387 // Revision 1.58  2004/11/09 17:11:16  rurban
388 // * revert to the wikidb ref passing. there's no memory abuse there.
389 // * use new wikidb->_cache->_id_cache[] instead of wikidb->_iwpcache, to effectively
390 //   store page ids with getPageLinks (GleanDescription) of all existing pages, which
391 //   are also needed at the rendering for linkExistingWikiWord().
392 //   pass options to pageiterator.
393 //   use this cache also for _get_pageid()
394 //   This saves about 8 SELECT count per page (num all pagelinks).
395 // * fix passing of all page fields to the pageiterator.
396 // * fix overlarge session data which got broken with the latest ACCESS_LOG_SQL changes
397 //
398 // Revision 1.57  2004/11/01 10:43:57  rurban
399 // seperate PassUser methods into seperate dir (memory usage)
400 // fix WikiUser (old) overlarge data session
401 // remove wikidb arg from various page class methods, use global ->_dbi instead
402 // ...
403 //
404 // Revision 1.56  2004/10/14 13:44:14  rurban
405 // fix lib/display.php:159: Warning[2]: Argument to array_reverse() should be an array
406 //
407 // Revision 1.55  2004/09/26 14:58:35  rurban
408 // naive SearchHighLight implementation
409 //
410 // Revision 1.54  2004/09/17 14:19:41  rurban
411 // disable Content-Type header for now, until it is fixed
412 //
413 // Revision 1.53  2004/06/25 14:29:20  rurban
414 // WikiGroup refactoring:
415 //   global group attached to user, code for not_current user.
416 //   improved helpers for special groups (avoid double invocations)
417 // new experimental config option ENABLE_XHTML_XML (fails with IE, and document.write())
418 // fixed a XHTML validation error on userprefs.tmpl
419 //
420 // Revision 1.52  2004/06/14 11:31:37  rurban
421 // renamed global $Theme to $WikiTheme (gforge nameclash)
422 // inherit PageList default options from PageList
423 //   default sortby=pagename
424 // use options in PageList_Selectable (limit, sortby, ...)
425 // added action revert, with button at action=diff
426 // added option regex to WikiAdminSearchReplace
427 //
428 // Revision 1.51  2004/05/18 16:23:39  rurban
429 // rename split_pagename to SplitPagename
430 //
431 // Revision 1.50  2004/05/04 22:34:25  rurban
432 // more pdf support
433 //
434 // Revision 1.49  2004/04/18 01:11:52  rurban
435 // more numeric pagename fixes.
436 // fixed action=upload with merge conflict warnings.
437 // charset changed from constant to global (dynamic utf-8 switching)
438 //
439
440 // For emacs users
441 // Local Variables:
442 // mode: php
443 // tab-width: 8
444 // c-basic-offset: 4
445 // c-hanging-comment-ender-p: nil
446 // indent-tabs-mode: nil
447 // End:
448 ?>