]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/display.php
During AJAX requests clear the AJAX format argument (for pagelist links, etc)
[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 /* only on ?action= */    
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         $request->setArg('format','');
91         $template = new Template('browse', $request,
92                                  array('revision' => $revision,
93                                        'CONTENT'  => $transformedContent,
94                                        ));
95         $html = GeneratePageAsXML($template, $pagename, $revision /*, 
96                                   array('VALID_LINKS' => $args['VALID_LINKS'])*/);
97         header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
98         echo $html;
99     } else {
100         $pagelist = null;
101         require_once('lib/WikiPlugin.php');
102         // Then the multi-page formats
103         // rss (if not already handled by RecentChanges)
104         // Need the pagelist from the first plugin
105         foreach($transformedContent->_content as $cached_element) {
106             if (is_a($cached_element, "Cached_PluginInvocation")) {
107                 $loader = new WikiPluginLoader;
108                 $markup = null;
109                 // return the first found pagelist
110                 $pagelist = $loader->expandPI($cached_element->_pi, $request, 
111                                               $markup, $pagename);
112                 if (is_a($pagelist, 'PageList'))
113                     break;
114             }
115         }
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             if ($format == 'pdf')
124                 $pagelist->addPage($page);
125         } else {
126             foreach ($pagelist->_pages as $page) {
127                 $name = $page->getName();
128                 if ($name != $pagename and $page->exists())
129                     $args['VALID_LINKS'][] = $name;
130             }
131         }
132         if ($format == 'pdf') {
133             require_once("lib/pdf.php");
134             array_unshift($args['VALID_LINKS'], $pagename);
135             ConvertAndDisplayPdfPageList($request, $pagelist, $args);
136         }
137         elseif ($format == 'ziphtml') { // need to fix links
138             require_once('lib/loadsave.php');
139             array_unshift($args['VALID_LINKS'], $pagename);
140             $request->setArg('zipname', FilenameForPage($pagename).".zip");
141             $request->setArg('pages', $args['VALID_LINKS']);
142             $request->setArg('format','');
143             MakeWikiZipHtml($request);
144         } // time-sorted RDF รก la RecentChanges 
145         elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
146             $args = $request->getArgs();
147             //$request->setArg('format','');
148             if ($pagename == _("RecentChanges")) {
149                 $template->printExpansion($args);
150             } else {
151                 require_once("lib/plugin/RecentChanges.php");
152                 $plugin = new WikiPlugin_RecentChanges();
153                 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
154             }
155         } elseif ($format == 'json') { // for faster autocompletion on searches
156             $req_args =& $request->args;
157             unset($req_args['format']);
158             $json = array('count' => count($pagelist->_pages),
159                           'list'  => $args['VALID_LINKS'],
160                           'args'  => $req_args,
161                           'phpwiki-version' => PHPWIKI_VERSION);
162             if (loadPhpExtension('json')) {
163                 $json_enc = json_encode($json);
164             } else {
165                 require_once("lib/pear/JSON.php");
166                 $j = new Services_JSON(); 
167                 $json_enc = $j->encode($json);
168             }
169             header("Content-Type: application/json");
170             die($json_enc);
171         } elseif ($format == 'rdf') { // all semantic relations and attributes
172             require_once("lib/SemanticWeb.php");
173             $rdf = new RdfWriter($request, $pagelist);
174             $rdf->format();
175         } elseif ($format == 'rdfs') {
176             require_once("lib/SemanticWeb.php");
177             $rdf = new RdfsWriter($request, $pagelist);
178             $rdf->format();
179         } elseif ($format == 'owl') { // or daml?
180             require_once("lib/SemanticWeb.php");
181             $rdf = new OwlWriter($request, $pagelist);
182             $rdf->format();
183         } else {
184             if (!in_array($pagename, array(_("LinkDatabase"))))
185                 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
186                               E_USER_WARNING);
187             $template = Template('browse', array('CONTENT' => $transformedContent));
188             GeneratePage($template, $pagetitle, $revision, $args);
189         }
190     }
191     $request->checkValidators();
192     flush();
193     return '';
194 }
195
196 function displayPage(&$request, $template=false) {
197     global $WikiTheme;
198     $pagename = $request->getArg('pagename');
199     $version = $request->getArg('version');
200     $page = $request->getPage();
201     if ($version) {
202         $revision = $page->getRevision($version);
203         if (!$revision)
204             NoSuchRevision($request, $page, $version);
205         /* Tell Google (and others) to ignore old versions of pages */
206         $toks['ROBOTS_META'] = "noindex,nofollow";
207     }
208     else {
209         $revision = $page->getCurrentRevision();
210     }
211     $format = $request->getArg('format');
212     if ($format == 'xml') {  // fast ajax: include page content asynchronously
213         global $charset;
214         header("Content-Type: text/xml");
215         echo "<","?xml version=\"1.0\" encoding=\"$charset\"?", ">\n";
216         // DOCTYPE html needed to allow unencoded entities like &nbsp; without !CDATA[]
217         echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
218   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',"\n";
219         if ($page->exists()) {
220             header("Last-Modified: " . Rfc1123DateTime($revision->get('mtime')));
221             $request->cacheControl();
222             $request->setArg('format','');
223             $page_content = $revision->getTransformedContent();
224             $page_content->printXML();
225             $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
226             $request->finish();
227         }
228         else {
229             $request->cacheControl();
230             echo('<div style="display:none;" />');
231             $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
232             $request->finish();
233             exit();
234         }
235     }
236
237     if (isSubPage($pagename)) {
238         $pages = explode(SUBPAGE_SEPARATOR, $pagename);
239         $last_page = array_pop($pages); // deletes last element from array as side-effect
240         $pageheader = HTML::span(HTML::a(array('href' => WikiURL($pages[0]),
241                                                'class' => 'pagetitle'
242                                               ),
243                                         $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
244         $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
245         array_shift($pages);
246         foreach ($pages as $p)  {
247             $pageheader->pushContent(HTML::a(array('href' => WikiURL($first_pages . $p),
248                                                   'class' => 'backlinks'),
249                                             $WikiTheme->maybeSplitWikiWord($p . SUBPAGE_SEPARATOR)));
250             $first_pages .= $p . SUBPAGE_SEPARATOR;
251         }
252         $backlink = HTML::a(array('href' => WikiURL($pagename,
253                                                     array('action' => _("BackLinks"))),
254                                   'class' => 'backlinks'),
255                             $WikiTheme->maybeSplitWikiWord($last_page));
256         $backlink->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
257         $pageheader->pushContent($backlink);
258     } else {
259         $pageheader = HTML::a(array('href' => WikiURL($pagename,
260                                                      array('action' => _("BackLinks"))),
261                                    'class' => 'backlinks'),
262                              $WikiTheme->maybeSplitWikiWord($pagename));
263         $pageheader->addTooltip(sprintf(_("BackLinks for %s"), $pagename));
264         if ($request->getArg('frame'))
265             $pageheader->setAttr('target', '_top');
266     }
267
268     $pagetitle = SplitPagename($pagename);
269     if (($redirect_from = $request->getArg('redirectfrom'))) {
270         $redirect_message = HTML::span(array('class' => 'redirectfrom'),
271                                        fmt("(Redirected from %s)",
272                                            RedirectorLink($redirect_from)));
273     // abuse the $redirected template var for some status update notice                                       
274     } elseif ($request->getArg('errormsg')) { 
275         $redirect_message = $request->getArg('errormsg');
276         $request->setArg('errormsg', false);
277     }
278
279     $request->appendValidators(array('pagerev' => $revision->getVersion(),
280                                      '%mtime' => $revision->get('mtime')));
281 /*
282     // FIXME: This is also in the template...
283     if ($request->getArg('action') != 'pdf' and !headers_sent()) {
284       // FIXME: enable MathML/SVG/... support
285       if (ENABLE_XHTML_XML
286              and (!isBrowserIE()
287                   and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
288             header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
289         else
290             header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
291     }
292 */
293
294     $toks['TITLE'] = $pagetitle;   // <title> tag
295     $toks['HEADER'] = $pageheader; // h1 with backlink
296     $toks['revision'] = $revision;
297
298     // On external searchengine (google) referrer, highlight the searchterm and 
299     // pass through the Searchhighlight actionpage.
300     if ($result = isExternalReferrer($request)) {
301         if (!empty($result['query'])) {
302             if (ENABLE_SEARCHHIGHLIGHT) {
303                 $request->_searchhighlight = $result;
304                 $request->appendValidators(array('%mtime' => time())); // force no cache(?)
305                 // Should be changed to check the engine and search term only
306                 // $request->setArg('nocache', 1); 
307                 $page_content = new TransformedText($revision->getPage(),
308                                                     $revision->getPackedContent(),
309                                                     $revision->getMetaData());
310                 /* Now add the SearchHighlight plugin to the top of the page, in memory only.
311                    You can parametrize this by changing the SearchHighlight action page.
312                 */
313                 if ($actionpage = $request->findActionPage('SearchHighlight')) {
314                     $actionpage = $request->getPage($actionpage);
315                     $actionrev = $actionpage->getCurrentRevision();
316                     $pagetitle = HTML(fmt("%s: %s", 
317                                           $actionpage->getName(),
318                                           $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
319                     $request->appendValidators(array('actionpagerev' => $actionrev->getVersion(),
320                                                      '%mtime' => $actionrev->get('mtime')));
321                     $toks['SEARCH_ENGINE'] = $result['engine'];
322                     $toks['SEARCH_ENGINE_URL'] = $result['engine_url'];
323                     $toks['SEARCH_TERM'] = $result['query'];
324                     //$toks['HEADER'] = HTML($actionpage->getName(),": ",$pageheader); // h1 with backlink
325                     $actioncontent = new TransformedText($actionrev->getPage(),
326                                                          $actionrev->getPackedContent(),
327                                                          $actionrev->getMetaData());
328                     // prepend the actionpage in front of the hightlighted content
329                     $toks['CONTENT'] = HTML($actioncontent, $page_content);
330                 }
331             }
332         } else {
333             $page_content = $revision->getTransformedContent();
334         }
335     } else {
336         $page_content = $revision->getTransformedContent();
337     }
338    
339     /* Check for special pagenames, which are no actionpages. */
340     /*
341     if ( $pagename == _("RecentVisitors")) {
342         $toks['ROBOTS_META']="noindex,follow";
343     } else
344     */
345     if ($pagename == _("SandBox")) {
346         $toks['ROBOTS_META']="noindex,nofollow";
347     } else if (!isset($toks['ROBOTS_META'])) {
348         $toks['ROBOTS_META'] = "index,follow";
349     }
350     if (!isset($toks['CONTENT']))
351         $toks['CONTENT'] = new Template('browse', $request, $page_content);
352     if (!empty($redirect_message))
353         $toks['redirected'] = $redirect_message;
354
355     // Massive performance problem parsing at run-time into all xml objects 
356     // looking for p's. Should be optional, if not removed at all.
357     //$toks['PAGE_DESCRIPTION'] = $page_content->getDescription();
358     $toks['PAGE_KEYWORDS'] = GleanKeywords($page);
359     if (!$template)
360         $template = new Template('html', $request);
361
362     // Handle other formats: So far we had html only.
363     // xml is requested by loaddump, rss is handled by RecentChanges, 
364     // pdf is a special action, but should be a format to dump multiple pages
365     // if the actionpage plugin returns a pagelist.
366     // rdf, owl, kbmodel, daml, ... are handled by SemanticWeb.
367     /* Only single page versions. rss only if not already handled by RecentChanges.
368      */
369     if (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
370         $template->printExpansion($toks);
371     } else {
372         // No pagelist here. Single page version only
373         require_once("lib/PageList.php");
374         $pagelist = new PageList();
375         $pagelist->addPage($page);
376         if ($format == 'pdf') {
377             require_once("lib/pdf.php");
378             $request->setArg('format','');
379             ConvertAndDisplayPdfPageList($request, $pagelist);
380         // time-sorted rdf a la RecentChanges
381         } elseif (in_array($format, array("rss91","rss2","rss","atom"))) {
382             //$request->setArg('format','');
383             if ($pagename == _("RecentChanges"))
384                 $template->printExpansion($toks);
385             else {    
386                 require_once("lib/plugin/RecentChanges.php");
387                 $plugin = new WikiPlugin_RecentChanges();
388                 $args = $request->getArgs();
389                 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
390             }
391         } elseif ($format == 'rdf') { // all semantic relations and attributes
392             require_once("lib/SemanticWeb.php");
393             $rdf = new RdfWriter($request, $pagelist);
394             $rdf->format();
395         } elseif ($format == 'owl') { // or daml?
396             require_once("lib/SemanticWeb.php");
397             $rdf = new OwlWriter($request, $pagelist);
398             $rdf->format();
399         } elseif ($format == 'json') { // include page content asynchronously
400             $request->setArg('format','');
401             if ($page->exists())
402                 $content = $page_content->asXML();
403             else
404                 $content = '';
405             $req_args = $request->args;
406             unset($req_args['format']);
407             // no meta-data so far, just the content
408             $json = array('content' => $content,
409                           'args'    => $req_args,
410                           'phpwiki-version' => PHPWIKI_VERSION);
411             if (loadPhpExtension('json')) {
412                 $json_enc = json_encode($json);
413             } else {
414                 require_once("lib/pear/JSON.php");
415                 $j = new Services_JSON(); 
416                 $json_enc = $j->encode($json);
417             }
418             header("Content-Type: application/json");
419             die($json_enc);
420         } else {
421             if (!in_array($pagename, array(_("LinkDatabase"))))
422                 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
423                               E_USER_WARNING);
424             $template->printExpansion($toks);
425         }
426     }
427     
428     $page->increaseHitCount();
429
430     if ($request->getArg('action') != 'pdf') {
431         $request->checkValidators();
432         flush();
433     }
434     return '';
435 }
436
437 // For emacs users
438 // Local Variables:
439 // mode: php
440 // tab-width: 8
441 // c-basic-offset: 4
442 // c-hanging-comment-ender-p: nil
443 // indent-tabs-mode: nil
444 // End:
445 ?>