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