2 // display.php: fetch page or get default content
5 require_once('lib/Template.php');
8 * Extract keywords from Category* links on page.
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()) {
21 if (preg_match($KeywordLinkRegexp, $link->getName(), $m))
22 $keywords[] = SplitPagename($m[0]);
24 $keywords[] = WIKI_NAME;
25 return join(', ', $keywords);
28 /** Make a link back to redirecting page.
30 * @param $pagename string Name of redirecting page.
31 * @return XmlContent Link to the redirecting page.
33 function RedirectorLink($pagename) {
34 $url = WikiURL($pagename, array('redirectfrom' => ''));
35 return HTML::a(array('class' => 'redirectfrom wiki',
40 /* only on ?action= */
41 function actionPage(&$request, $action) {
44 $pagename = $request->getArg('pagename');
45 $version = $request->getArg('version');
47 $page = $request->getPage();
48 $revision = $page->getCurrentRevision();
50 $dbi = $request->getDbh();
51 $actionpage = $dbi->getPage($action);
52 $actionrev = $actionpage->getCurrentRevision();
54 $pagetitle = HTML(fmt("%s: %s",
55 $actionpage->getName(),
56 $WikiTheme->linkExistingWikiWord($pagename, false, $version)));
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')));
65 $transformedContent = $actionrev->getTransformedContent();
67 /* Optionally tell google (and others) not to take notice of action pages.
68 RecentChanges or AllPages might be an exception.
71 if (GOOGLE_LINKS_NOFOLLOW)
72 $args = array('ROBOTS_META' => "noindex,nofollow");
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.
80 $format = $request->getArg('format');
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,
95 $html = GeneratePageAsXML($template, $pagename, $revision /*,
96 array('VALID_LINKS' => $args['VALID_LINKS'])*/);
97 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
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;
109 // return the first found pagelist
110 $pagelist = $loader->expandPI($cached_element->_pi, $request,
112 if (is_a($pagelist, 'PageList'))
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.",
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);
126 foreach ($pagelist->_pages as $page) {
127 $name = $page->getName();
128 if ($name != $pagename and $page->exists())
129 $args['VALID_LINKS'][] = $name;
132 if ($format == 'pdf') {
133 require_once("lib/pdf.php");
134 array_unshift($args['VALID_LINKS'], $pagename);
135 ConvertAndDisplayPdfPageList($request, $pagelist, $args);
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);
151 require_once("lib/plugin/RecentChanges.php");
152 $plugin = new WikiPlugin_RecentChanges();
153 return $plugin->format($plugin->getChanges($request->_dbi, $args), $args);
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'],
161 'phpwiki-version' => PHPWIKI_VERSION);
162 if (loadPhpExtension('json')) {
163 $json_enc = json_encode($json);
165 require_once("lib/pear/JSON.php");
166 $j = new Services_JSON();
167 $json_enc = $j->encode($json);
169 header("Content-Type: application/json");
171 } elseif ($format == 'rdf') { // all semantic relations and attributes
172 require_once("lib/SemanticWeb.php");
173 $rdf = new RdfWriter($request, $pagelist);
175 } elseif ($format == 'rdfs') {
176 require_once("lib/SemanticWeb.php");
177 $rdf = new RdfsWriter($request, $pagelist);
179 } elseif ($format == 'owl') { // or daml?
180 require_once("lib/SemanticWeb.php");
181 $rdf = new OwlWriter($request, $pagelist);
184 if (!in_array($pagename, array(_("LinkDatabase"))))
185 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
187 $template = Template('browse', array('CONTENT' => $transformedContent));
188 GeneratePage($template, $pagetitle, $revision, $args);
191 $request->checkValidators();
196 function displayPage(&$request, $template=false) {
198 $pagename = $request->getArg('pagename');
199 $version = $request->getArg('version');
200 $page = $request->getPage();
202 $revision = $page->getRevision($version);
204 NoSuchRevision($request, $page, $version);
205 /* Tell Google (and others) to ignore old versions of pages */
206 $toks['ROBOTS_META'] = "noindex,nofollow";
209 $revision = $page->getCurrentRevision();
211 $format = $request->getArg('format');
212 if ($format == 'xml') { // fast ajax: include page content asynchronously
214 header("Content-Type: text/xml");
215 echo "<","?xml version=\"1.0\" encoding=\"$charset\"?", ">\n";
216 // DOCTYPE html needed to allow unencoded entities like 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
229 $request->cacheControl();
230 echo('<div style="display:none;" />');
231 $request->_is_buffering_output = false; // avoid wrong Content-Length with errors
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'
243 $WikiTheme->maybeSplitWikiWord($pages[0] . SUBPAGE_SEPARATOR)));
244 $first_pages = $pages[0] . SUBPAGE_SEPARATOR;
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;
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);
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');
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);
279 $request->appendValidators(array('pagerev' => $revision->getVersion(),
280 '%mtime' => $revision->get('mtime')));
282 // FIXME: This is also in the template...
283 if ($request->getArg('action') != 'pdf' and !headers_sent()) {
284 // FIXME: enable MathML/SVG/... support
287 and strstr($request->get('HTTP_ACCEPT'),'application/xhtml+xml')))
288 header("Content-Type: application/xhtml+xml; charset=" . $GLOBALS['charset']);
290 header("Content-Type: text/html; charset=" . $GLOBALS['charset']);
294 $toks['TITLE'] = $pagetitle; // <title> tag
295 $toks['HEADER'] = $pageheader; // h1 with backlink
296 $toks['revision'] = $revision;
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.
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);
333 $page_content = $revision->getTransformedContent();
336 $page_content = $revision->getTransformedContent();
339 /* Check for special pagenames, which are no actionpages. */
341 if ( $pagename == _("RecentVisitors")) {
342 $toks['ROBOTS_META']="noindex,follow";
345 if ($pagename == _("SandBox")) {
346 $toks['ROBOTS_META']="noindex,nofollow";
347 } else if (!isset($toks['ROBOTS_META'])) {
348 $toks['ROBOTS_META'] = "index,follow";
350 if (!isset($toks['CONTENT']))
351 $toks['CONTENT'] = new Template('browse', $request, $page_content);
352 if (!empty($redirect_message))
353 $toks['redirected'] = $redirect_message;
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);
360 $template = new Template('html', $request);
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.
369 if (!$format or $format == 'html' or $format == 'sidebar' or $format == 'contribs') {
370 $template->printExpansion($toks);
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);
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);
391 } elseif ($format == 'rdf') { // all semantic relations and attributes
392 require_once("lib/SemanticWeb.php");
393 $rdf = new RdfWriter($request, $pagelist);
395 } elseif ($format == 'owl') { // or daml?
396 require_once("lib/SemanticWeb.php");
397 $rdf = new OwlWriter($request, $pagelist);
399 } elseif ($format == 'json') { // include page content asynchronously
400 $request->setArg('format','');
402 $content = $page_content->asXML();
405 $req_args = $request->args;
406 unset($req_args['format']);
407 // no meta-data so far, just the content
408 $json = array('content' => $content,
410 'phpwiki-version' => PHPWIKI_VERSION);
411 if (loadPhpExtension('json')) {
412 $json_enc = json_encode($json);
414 require_once("lib/pear/JSON.php");
415 $j = new Services_JSON();
416 $json_enc = $j->encode($json);
418 header("Content-Type: application/json");
421 if (!in_array($pagename, array(_("LinkDatabase"))))
422 trigger_error(sprintf(_("Unsupported argument: %s=%s"),"format",$format),
424 $template->printExpansion($toks);
428 $page->increaseHitCount();
430 if ($request->getArg('action') != 'pdf') {
431 $request->checkValidators();
442 // c-hanging-comment-ender-p: nil
443 // indent-tabs-mode: nil