]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/display.php
elseif
[SourceForge/phpwiki.git] / lib / display.php
1 <?php
2 // $Id$
3 /* Copyright (C) 2004-2011 $ThePhpWikiProgrammingTeam
4  *
5  * This file is part of PhpWiki.
6  *
7  * PhpWiki is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * PhpWiki is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 // display.php: fetch page or get default content
23
24 require_once('lib/Template.php');
25
26 /**
27  * Extract keywords from Category* links on page.
28  */
29 function GleanKeywords ($page) {
30     if (!defined('KEYWORDS')) return '';
31     require_once("lib/TextSearchQuery.php");
32     $search = new TextSearchQuery(KEYWORDS, true);
33     $KeywordLinkRegexp = $search->asRegexp();
34     // iterate over the pagelinks (could be a large number) [15ms on PluginManager]
35     // or do a titleSearch and check the categories if they are linked?
36     $links = $page->getPageLinks();
37     $keywords[] = SplitPagename($page->getName());
38     while ($link = $links->next()) {
39         $m = array();
40         if (preg_match($KeywordLinkRegexp, $link->getName(), $m))
41             $keywords[] = SplitPagename($m[0]);
42     }
43     $keywords[] = WIKI_NAME;
44     return join(', ', $keywords);
45 }
46
47 /** Make a link back to redirecting page.
48  *
49  * @param $pagename string  Name of redirecting page.
50  * @return XmlContent Link to the redirecting page.
51  */
52 function RedirectorLink($pagename) {
53     $url = WikiURL($pagename, array('redirectfrom' => ''));
54     return HTML::a(array('class' => 'redirectfrom wiki',
55                          'href' => $url),
56                    $pagename);
57 }
58
59 /* only on ?action= */
60 function actionPage(&$request, $action) {
61     global $WikiTheme;
62     global $robots;
63
64     $pagename = $request->getArg('pagename');
65     $version = $request->getArg('version');
66
67     $page = $request->getPage();
68     $revision = $page->getCurrentRevision();
69
70     $dbi = $request->getDbh();
71     $actionpage = $dbi->getPage($action);
72     $actionrev = $actionpage->getCurrentRevision();
73
74     $pagetitle = HTML(fmt("%s: %s",
75                           $actionpage->getName(),
76                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
77
78     $request->setValidators(array('pageversion' => $revision->getVersion(),
79                                   '%mtime' => $revision->get('mtime')));
80     $request->appendValidators(array('pagerev' => $revision->getVersion(),
81                                      '%mtime' => $revision->get('mtime')));
82     $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
83                                      '%mtime' => $actionrev->get('mtime')));
84
85     $transformedContent = $actionrev->getTransformedContent();
86
87     /* Optionally tell google (and others) not to take notice of action pages.
88        RecentChanges or AllPages might be an exception.
89     */
90     $args = array();
91     if (GOOGLE_LINKS_NOFOLLOW) {
92         $robots = "noindex,nofollow";
93         $args = array('ROBOTS_META' => $robots);
94     }
95
96     /* Handle other formats: So far we had html only.
97        xml is requested by loaddump, rss is handled by recentchanges,
98        pdf is a special action, but should be a format to dump multiple pages
99        if the actionpage plugin returns a pagelist.
100        rdf and owl are handled by SemanticWeb.
101     */
102     $format = $request->getArg('format');
103
104     /* At first the single page formats: html, xml */
105     if ($pagename == _("LinkDatabase")) {
106         $template = Template('browse', array('CONTENT' => $transformedContent));
107         GeneratePage($template, $pagetitle, $revision, $args);
108     } elseif (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
109         $template = Template('browse', array('CONTENT' => $transformedContent));
110         GeneratePage($template, $pagetitle, $revision, $args);
111     } elseif ($format == 'xml') {
112         $request->setArg('format','');
113         $template = new Template('browse', $request,
114                                  array('revision' => $revision,
115                                        'CONTENT'  => $transformedContent,
116                        ));
117         $html = GeneratePageAsXML($template, $pagename, $revision /*,
118                   array('VALID_LINKS' => $args['VALID_LINKS'])*/);
119         header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
120         echo $html;
121     } else {
122         $pagelist = null;
123         require_once('lib/WikiPlugin.php');
124         // Then the multi-page formats
125         // rss (if not already handled by RecentChanges)
126         // Need the pagelist from the first plugin
127         foreach($transformedContent->_content as $cached_element) {
128             if (is_a($cached_element, "Cached_PluginInvocation")) {
129                 $loader = new WikiPluginLoader;
130                 $markup = null;
131                 // return the first found pagelist
132                 $pagelist = $loader->expandPI($cached_element->_pi, $request,
133                                               $markup, $pagename);
134                 if (is_a($pagelist, 'PageList'))
135                     break;
136             }
137         }
138         if (!$pagelist or !is_a($pagelist, 'PageList')) {
139             if (!in_array($format, array("rss91","rss2","rss","atom","rdf")))
140             trigger_error(sprintf("Format %s requires an actionpage returning a pagelist.",
141                       $format)
142                   ."\n".("Fall back to single page mode"), E_USER_WARNING);
143             require_once('lib/PageList.php');
144             $pagelist = new PageList();
145             if ($format == 'pdf')
146                 $pagelist->addPage($page);
147         } else {
148             foreach ($pagelist->_pages as $page) {
149                 $name = $page->getName();
150                 if ($name != $pagename and $page->exists())
151                     $args['VALID_LINKS'][] = $name;
152             }
153         }
154         if ($format == 'pdf') {
155             require_once("lib/pdf.php");
156             array_unshift($args['VALID_LINKS'], $pagename);
157             ConvertAndDisplayPdfPageList($request, $pagelist, $args);
158         }
159         elseif ($format == 'ziphtml') { // need to fix links
160             require_once('lib/loadsave.php');
161             array_unshift($args['VALID_LINKS'], $pagename);
162             $request->setArg('zipname', FilenameForPage($pagename).".zip");
163             $request->setArg('pages', $args['VALID_LINKS']);
164             $request->setArg('format','');
165             MakeWikiZipHtml($request);
166         } // time-sorted RDF à la RecentChanges
167         elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
168             $args = $request->getArgs();
169             //$request->setArg('format','');
170             if ($pagename == _("RecentChanges")) {
171                 $template->printExpansion($args);
172             } else {
173                 require_once("lib/plugin/RecentChanges.php");
174                 $plugin = new WikiPlugin_RecentChanges();
175                 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
176             }
177         } elseif ($format == 'json') { // for faster autocompletion on searches
178             $req_args =& $request->args;
179             unset($req_args['format']);
180             $json = array('count' => count($pagelist->_pages),
181                           'list'  => $args['VALID_LINKS'],
182                           'args'  => $req_args,
183                           'phpwiki-version' => PHPWIKI_VERSION);
184             if (loadPhpExtension('json')) {
185                 $json_enc = json_encode($json);
186             } else {
187                 require_once("lib/pear/JSON.php");
188                 $j = new Services_JSON();
189                 $json_enc = $j->encode($json);
190             }
191             header("Content-Type: application/json");
192             die($json_enc);
193         } elseif ($format == 'rdf') { // all semantic relations and attributes
194             require_once("lib/SemanticWeb.php");
195             $rdf = new RdfWriter($request, $pagelist);
196             $rdf->format();
197         } elseif ($format == 'rdfs') {
198             require_once("lib/SemanticWeb.php");
199             $rdf = new RdfsWriter($request, $pagelist);
200             $rdf->format();
201         } elseif ($format == 'owl') { // or daml?
202             require_once("lib/SemanticWeb.php");
203             $rdf = new OwlWriter($request, $pagelist);
204             $rdf->format();
205         } else {
206             if (!in_array($pagename, array(_("LinkDatabase"))))
207             trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
208                           E_USER_WARNING);
209             $template = Template('browse', array('CONTENT' => $transformedContent));
210             GeneratePage($template, $pagetitle, $revision, $args);
211         }
212     }
213     $request->checkValidators();
214     flush();
215     return '';
216 }
217
218 function displayPage(&$request, $template=false) {
219     global $WikiTheme;
220     global $robots;
221     $pagename = $request->getArg('pagename');
222     $version = $request->getArg('version');
223     $page = $request->getPage();
224
225     if ($version) {
226         $revision = $page->getRevision($version);
227         if (!$revision)
228             NoSuchRevision($request, $page, $version);
229         /* Tell Google (and others) to ignore old versions of pages */
230         $robots = "noindex,nofollow";
231         $toks['ROBOTS_META'] = $robots;
232     } else {
233         $revision = $page->getCurrentRevision();
234     }
235     $format = $request->getArg('format');
236     if ($format == 'xml') {  // fast ajax: include page content asynchronously
237         global $charset;
238         header("Content-Type: text/xml");
239         echo "<","?xml version=\"1.0\" encoding=\"$charset\"?", ">\n";
240         // DOCTYPE html needed to allow unencoded entities like &nbsp; without !CDATA[]
241         echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
242   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',"\n";
243         if ($page->exists()) {
244             header("Last-Modified: " . Rfc1123DateTime($revision->get('mtime')));
245             $request->cacheControl();
246             $request->setArg('format','');
247             $page_content = $revision->getTransformedContent();
248             $page_content->printXML();
249             $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
250             $request->finish();
251         } else {
252             $request->cacheControl();
253             echo('<div style="display:none;" />');
254             $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
255             $request->finish();
256             exit();
257         }
258     }
259
260     if (isSubPage($pagename)) {
261         $pages = explode(SUBPAGE_SEPARATOR, $pagename);
262         $last_page = array_pop($pages); // deletes last element from array as side-effect
263         $pageheader = HTML::span(HTML::a(array('href' => WikiURL($pages[0]),
264                                                'class' => 'pagetitle'
265                                               ),
266                                         $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
267         $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
268         array_shift($pages);
269         foreach ($pages as $p)  {
270             $pageheader->pushContent(HTML::a(array('href' => WikiURL($first_pages . $p),
271                                                   'class' => 'backlinks'),
272                                             $WikiTheme->maybeSplitWikiWord($p . SUBPAGE_SEPARATOR)));
273             $first_pages .= $p . SUBPAGE_SEPARATOR;
274         }
275         $backlink = HTML::a(array('href' => WikiURL($pagename,
276                                                     array('action' => _("BackLinks"))),
277                                   'class' => 'backlinks'),
278                             $WikiTheme->maybeSplitWikiWord($last_page));
279         $backlink->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
280         $pageheader->pushContent($backlink);
281     } else {
282         $pageheader = HTML::a(array('href' => WikiURL($pagename,
283                                                      array('action' => _("BackLinks"))),
284                                    'class' => 'backlinks'),
285                              $WikiTheme->maybeSplitWikiWord($pagename));
286         $pageheader->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
287         if ($request->getArg('frame'))
288             $pageheader->setAttr('target', '_top');
289     }
290
291     $pagetitle = SplitPagename($pagename);
292     if (($redirect_from = $request->getArg('redirectfrom'))) {
293         $redirect_message = HTML::span(array('class' => 'redirectfrom'),
294                                        fmt("(Redirected from %s)",
295                                            RedirectorLink($redirect_from)));
296     // abuse the $redirected template var for some status update notice
297     } elseif ($request->getArg('errormsg')) {
298         $redirect_message = HTML::p(array('class' => 'error'),
299                                           $request->getArg('errormsg'));
300         $request->setArg('errormsg', false);
301     } elseif ($request->getArg('warningmsg')) {
302         $redirect_message = HTML::p(array('class' => 'warning_msg'),
303                                           $request->getArg('warningmsg'));
304         $request->setArg('errormsg', false);
305     }
306
307     $request->appendValidators(array('pagerev' => $revision->getVersion(),
308                                      '%mtime' => $revision->get('mtime')));
309 /*
310     // FIXME: This is also in the template...
311     if ($request->getArg('action') != 'pdf' and !headers_sent()) {
312       // FIXME: enable MathML/SVG/... support
313       if (ENABLE_XHTML_XML
314              and (!isBrowserIE()
315                   and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
316             header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
317         else
318             header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
319     }
320 */
321
322     $toks['TITLE'] = $pagetitle;   // <title> tag
323     $toks['HEADER'] = $pageheader; // h1 with backlink
324     $toks['revision'] = $revision;
325
326     // On external searchengine (google) referrer, highlight the searchterm and
327     // pass through the Searchhighlight actionpage.
328     if ($result = isExternalReferrer($request)) {
329         if (!empty($result['query'])) {
330             if (ENABLE_SEARCHHIGHLIGHT) {
331                 $request->_searchhighlight = $result;
332                 $request->appendValidators(array('%mtime' => time())); // force no cache(?)
333                 // Should be changed to check the engine and search term only
334                 // $request->setArg('nocache', 1);
335                 $page_content = new TransformedText($revision->getPage(),
336                                                     $revision->getPackedContent(),
337                                                     $revision->getMetaData());
338         /* Now add the SearchHighlight plugin to the top of the page, in memory only.
339            You can parametrize this by changing the SearchHighlight action page.
340         */
341                 if ($actionpage = $request->findActionPage('SearchHighlight')) {
342                     $actionpage = $request->getPage($actionpage);
343                     $actionrev = $actionpage->getCurrentRevision();
344                     $pagetitle = HTML(fmt("%s: %s",
345                                           $actionpage->getName(),
346                                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
347                     $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
348                                                      '%mtime' => $actionrev->get('mtime')));
349                     $toks['SEARCH_ENGINE'] = $result['engine'];
350                     $toks['SEARCH_ENGINE_URL'] = $result['engine_url'];
351                     $toks['SEARCH_TERM'] = $result['query'];
352                     //$toks['HEADER'] = HTML($actionpage->getName(),": ",$pageheader); // h1 with backlink
353                     $actioncontent = new TransformedText($actionrev->getPage(),
354                                                          $actionrev->getPackedContent(),
355                                                          $actionrev->getMetaData());
356                     // prepend the actionpage in front of the hightlighted content
357                     $toks['CONTENT'] = HTML($actioncontent, $page_content);
358                 }
359             }
360         } else {
361             $page_content = $revision->getTransformedContent();
362         }
363     } else {
364         $page_content = $revision->getTransformedContent();
365     }
366
367     if ($pagename == _("SandBox")) {
368         $robots = "noindex,nofollow";
369         $toks['ROBOTS_META'] = $robots;
370     } elseif (isActionPage($pagename)) {
371         $robots = "noindex,nofollow";
372         $toks['ROBOTS_META'] = $robots;
373     } elseif (!isset($toks['ROBOTS_META'])) {
374         $robots = "index,follow";
375         $toks['ROBOTS_META'] = $robots;
376     }
377     if (!isset($toks['CONTENT']))
378         $toks['CONTENT'] = new Template('browse', $request, $page_content);
379     if (!empty($redirect_message))
380         $toks['redirected'] = $redirect_message;
381
382     // Massive performance problem parsing at run-time into all xml objects
383     // looking for p's. Should be optional, if not removed at all.
384     //$toks['PAGE_DESCRIPTION'] = $page_content->getDescription();
385     $toks['PAGE_KEYWORDS'] = GleanKeywords($page);
386     if (!$template)
387         $template = new Template('html', $request);
388
389     // Handle other formats: So far we had html only.
390     // xml is requested by loaddump, rss is handled by RecentChanges,
391     // pdf is a special action, but should be a format to dump multiple pages
392     // if the actionpage plugin returns a pagelist.
393     // rdf, owl, kbmodel, daml, ... are handled by SemanticWeb.
394     /* Only single page versions. rss only if not already handled by RecentChanges.
395      */
396     if (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
397         $template->printExpansion($toks);
398     } else {
399         // No pagelist here. Single page version only
400         require_once("lib/PageList.php");
401         $pagelist = new PageList();
402         $pagelist->addPage($page);
403         if ($format == 'pdf') {
404             require_once("lib/pdf.php");
405             $request->setArg('format','');
406             ConvertAndDisplayPdfPageList($request, $pagelist);
407             // time-sorted rdf a la RecentChanges
408         } elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
409             //$request->setArg('format','');
410             if ($pagename == _("RecentChanges"))
411                 $template->printExpansion($toks);
412             else {
413                 require_once("lib/plugin/RecentChanges.php");
414             $plugin = new WikiPlugin_RecentChanges();
415                 $args = $request->getArgs();
416                 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
417             }
418         } elseif ($format == 'rdf') { // all semantic relations and attributes
419             require_once("lib/SemanticWeb.php");
420             $rdf = new RdfWriter($request, $pagelist);
421             $rdf->format();
422         } elseif ($format == 'owl') { // or daml?
423             require_once("lib/SemanticWeb.php");
424             $rdf = new OwlWriter($request, $pagelist);
425             $rdf->format();
426         } elseif ($format == 'json') { // include page content asynchronously
427             $request->setArg('format','');
428             if ($page->exists())
429                 $content = $page_content->asXML();
430             else
431                 $content = '';
432             $req_args = $request->args;
433             unset($req_args['format']);
434             // no meta-data so far, just the content
435             $json = array('content' => $content,
436                           'args'    => $req_args,
437                           'phpwiki-version' => PHPWIKI_VERSION);
438             if (loadPhpExtension('json')) {
439                 $json_enc = json_encode($json);
440             } else {
441                 require_once("lib/pear/JSON.php");
442                 $j = new Services_JSON();
443                 $json_enc = $j->encode($json);
444             }
445             header("Content-Type: application/json");
446             die($json_enc);
447         } else {
448             if (!in_array($pagename, array(_("LinkDatabase"))))
449             trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
450                           E_USER_WARNING);
451             $template->printExpansion($toks);
452         }
453     }
454
455     $page->increaseHitCount();
456
457     if ($request->getArg('action') != 'pdf') {
458         $request->checkValidators();
459         flush();
460     }
461     return '';
462 }
463
464 // Local Variables:
465 // mode: php
466 // tab-width: 8
467 // c-basic-offset: 4
468 // c-hanging-comment-ender-p: nil
469 // indent-tabs-mode: nil
470 // End:
471 ?>