PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/gforge/plugins/wiki/www/lib/CachedMarkup.php

https://github.com/neymanna/fusionforge
PHP | 556 lines | 523 code | 6 blank | 27 comment | 13 complexity | c579f937b260ea234451e274e917bc6f MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. rcs_id('$Id: CachedMarkup.php,v 1.35 2005/04/23 11:18:58 rurban Exp $');
  3. /* Copyright (C) 2002 Geoffrey T. Dairiki <dairiki@dairiki.org>
  4. * Copyright (C) 2004, 2005 $ThePhpWikiProgrammingTeam
  5. *
  6. * This file is part of PhpWiki.
  7. *
  8. * PhpWiki is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * PhpWiki is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with PhpWiki; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. class CacheableMarkup extends XmlContent {
  23. function CacheableMarkup($content, $basepage) {
  24. $this->_basepage = $basepage;
  25. $this->_buf = '';
  26. $this->_content = array();
  27. $this->_append($content);
  28. if ($this->_buf != '')
  29. $this->_content[] = $this->_buf;
  30. unset($this->_buf);
  31. }
  32. function pack() {
  33. if (function_exists('gzcompress'))
  34. return gzcompress(serialize($this), 9);
  35. return serialize($this);
  36. // FIXME: probably should implement some sort of "compression"
  37. // when no gzcompress is available.
  38. }
  39. function unpack($packed) {
  40. if (!$packed)
  41. return false;
  42. // ZLIB format has a five bit checksum in it's header.
  43. // Lets check for sanity.
  44. if (((ord($packed[0]) * 256 + ord($packed[1])) % 31 == 0)
  45. and (substr($packed,0,2) == "\037\213")
  46. or (substr($packed,0,2) == "x\332")) // 120, 218
  47. {
  48. if (function_exists('gzuncompress')) {
  49. // Looks like ZLIB.
  50. $data = gzuncompress($packed);
  51. return unserialize($data);
  52. } else {
  53. // user our php lib. TESTME
  54. include_once("ziplib.php");
  55. $zip = new ZipReader($packed);
  56. list(,$data,$§attrib) = $zip->readFile();
  57. return unserialize($data);
  58. }
  59. }
  60. if (substr($packed,0,2) == "O:") {
  61. // Looks like a serialized object
  62. return unserialize($packed);
  63. }
  64. if (preg_match("/^\w+$/", $packed))
  65. return $packed;
  66. // happened with _BackendInfo problem also.
  67. trigger_error("Can't unpack bad cached markup. Probably php_zlib extension not loaded.",
  68. E_USER_WARNING);
  69. return false;
  70. }
  71. /** Get names of wikipages linked to.
  72. *
  73. * @return array
  74. * A list of wiki page names (strings).
  75. */
  76. function getWikiPageLinks() {
  77. include_once('lib/WikiPlugin.php');
  78. $ploader = new WikiPluginLoader();
  79. $links = array();
  80. foreach ($this->_content as $item) {
  81. if (!isa($item, 'Cached_DynamicContent'))
  82. continue;
  83. if (!($item_links = $item->getWikiPageLinks($this->_basepage)))
  84. continue;
  85. foreach ($item_links as $pagename)
  86. if (is_string($pagename) and $pagename != '')
  87. $links[] = $pagename;
  88. }
  89. return array_unique($links);
  90. }
  91. /** Get link info.
  92. *
  93. * This is here to support the XML-RPC listLinks() method.
  94. *
  95. * @return array
  96. * Returns an array of hashes.
  97. */
  98. function getLinkInfo() {
  99. $link = array();
  100. foreach ($this->_content as $link) {
  101. if (! isa($link, 'Cached_Link'))
  102. continue;
  103. $info = $link->getLinkInfo($this->_basepage);
  104. $links[$info->href] = $info;
  105. }
  106. return array_values($links);
  107. }
  108. function _append($item) {
  109. if (is_array($item)) {
  110. foreach ($item as $subitem)
  111. $this->_append($subitem);
  112. }
  113. elseif (!is_object($item)) {
  114. $this->_buf .= $this->_quote((string) $item);
  115. }
  116. elseif (isa($item, 'Cached_DynamicContent')) {
  117. if ($this->_buf) {
  118. $this->_content[] = $this->_buf;
  119. $this->_buf = '';
  120. }
  121. $this->_content[] = $item;
  122. }
  123. elseif (isa($item, 'XmlElement')) {
  124. if ($item->isEmpty()) {
  125. $this->_buf .= $item->emptyTag();
  126. }
  127. else {
  128. $this->_buf .= $item->startTag();
  129. foreach ($item->getContent() as $subitem)
  130. $this->_append($subitem);
  131. $this->_buf .= "</$item->_tag>";
  132. if (!isset($this->_description) and $item->getTag() == 'p')
  133. $this->_glean_description($item->asString());
  134. }
  135. if (!$item->isInlineElement())
  136. $this->_buf .= "\n";
  137. }
  138. elseif (isa($item, 'XmlContent')) {
  139. foreach ($item->getContent() as $item)
  140. $this->_append($item);
  141. }
  142. elseif (method_exists($item, 'asXML')) {
  143. $this->_buf .= $item->asXML();
  144. }
  145. elseif (method_exists($item, 'asString')) {
  146. $this->_buf .= $this->_quote($item->asString());
  147. }
  148. else {
  149. $this->_buf .= sprintf("==Object(%s)==", get_class($item));
  150. }
  151. }
  152. function _glean_description($text) {
  153. static $two_sentences;
  154. if (!$two_sentences) {
  155. $two_sentences = pcre_fix_posix_classes("[.?!][\")]*\s+[\"(]*[[:upper:])]"
  156. . ".*"
  157. . "[.?!][\")]*\s*[\"(]*([[:upper:])]|$)");
  158. }
  159. if (!isset($this->_description) and preg_match("/$two_sentences/sx", $text))
  160. $this->_description = preg_replace("/\s*\n\s*/", " ", trim($text));
  161. }
  162. /**
  163. * Guess a short description of the page.
  164. *
  165. * Algorithm:
  166. *
  167. * This algorithm was suggested on MeatballWiki by
  168. * Alex Schroeder <kensanata@yahoo.com>.
  169. *
  170. * Use the first paragraph in the page which contains at least two
  171. * sentences.
  172. *
  173. * @see http://www.usemod.com/cgi-bin/mb.pl?MeatballWikiSuggestions
  174. *
  175. * @return string
  176. */
  177. function getDescription () {
  178. return isset($this->_description) ? $this->_description : '';
  179. }
  180. function asXML () {
  181. $xml = '';
  182. $basepage = $this->_basepage;
  183. foreach ($this->_content as $item) {
  184. if (is_string($item)) {
  185. $xml .= $item;
  186. }
  187. elseif (is_subclass_of($item,
  188. check_php_version(5)
  189. ? 'Cached_DynamicContent'
  190. : 'cached_dynamiccontent'))
  191. {
  192. $val = $item->expand($basepage, $this);
  193. $xml .= $val->asXML();
  194. }
  195. else {
  196. $xml .= $item->asXML();
  197. }
  198. }
  199. return $xml;
  200. }
  201. function printXML () {
  202. $basepage = $this->_basepage;
  203. // _content might be changed from a plugin (CreateToc)
  204. for ($i=0; $i < count($this->_content); $i++) {
  205. $item = $this->_content[$i];
  206. if (is_string($item)) {
  207. print $item;
  208. }
  209. elseif (is_subclass_of($item,
  210. check_php_version(5)
  211. ? 'Cached_DynamicContent'
  212. : 'cached_dynamiccontent'))
  213. { // give the content the chance to know about itself or even
  214. // to change itself
  215. $val = $item->expand($basepage, $this);
  216. $val->printXML();
  217. }
  218. else {
  219. $item->printXML();
  220. }
  221. }
  222. }
  223. }
  224. /**
  225. * The base class for all dynamic content.
  226. *
  227. * Dynamic content is anything that can change even when the original
  228. * wiki-text from which it was parsed is unchanged.
  229. */
  230. class Cached_DynamicContent {
  231. function cache(&$cache) {
  232. $cache[] = $this;
  233. }
  234. function expand($basepage, &$obj) {
  235. trigger_error("Pure virtual", E_USER_ERROR);
  236. }
  237. function getWikiPageLinks($basepage) {
  238. return false;
  239. }
  240. }
  241. class XmlRpc_LinkInfo {
  242. function XmlRpc_LinkInfo($page, $type, $href) {
  243. $this->page = $page;
  244. $this->type = $type;
  245. $this->href = $href;
  246. //$this->pageref = str_replace("/RPC2.php", "/index.php", $href);
  247. }
  248. }
  249. class Cached_Link extends Cached_DynamicContent {
  250. function isInlineElement() {
  251. return true;
  252. }
  253. /** Get link info (for XML-RPC support)
  254. *
  255. * This is here to support the XML-RPC listLinks method.
  256. * (See http://www.ecyrd.com/JSPWiki/Wiki.jsp?page=WikiRPCInterface)
  257. */
  258. function getLinkInfo($basepage) {
  259. return new XmlRpc_LinkInfo($this->_getName($basepage),
  260. $this->_getType(),
  261. $this->_getURL($basepage));
  262. }
  263. function _getURL($basepage) {
  264. return $this->_url;
  265. }
  266. }
  267. class Cached_WikiLink extends Cached_Link {
  268. function Cached_WikiLink ($page, $label = false, $anchor = false) {
  269. $this->_page = $page;
  270. if ($anchor)
  271. $this->_anchor = $anchor;
  272. if ($label and $label != $page)
  273. $this->_label = $label;
  274. $this->_basepage = false;
  275. }
  276. function _getType() {
  277. return 'internal';
  278. }
  279. function getPagename($basepage) {
  280. $page = new WikiPageName($this->_page, $basepage);
  281. if ($page->isValid()) return $page->name;
  282. else return false;
  283. }
  284. function getWikiPageLinks($basepage) {
  285. if ($basepage == '') return false;
  286. if ($link = $this->getPagename($basepage)) return array($link);
  287. else return false;
  288. }
  289. function _getName($basepage) {
  290. return $this->getPagename($basepage);
  291. }
  292. function _getURL($basepage) {
  293. return WikiURL($this->getPagename($basepage));
  294. //return WikiURL($this->getPagename($basepage), false, 'abs_url');
  295. }
  296. function expand($basepage, &$markup) {
  297. $this->_basepage = $basepage;
  298. $label = isset($this->_label) ? $this->_label : false;
  299. $anchor = isset($this->_anchor) ? (string)$this->_anchor : '';
  300. $page = new WikiPageName($this->_page, $basepage, $anchor);
  301. if ($page->isValid()) return WikiLink($page, 'auto', $label);
  302. else return HTML($label);
  303. }
  304. function asXML() {
  305. $label = isset($this->_label) ? $this->_label : false;
  306. $anchor = isset($this->_anchor) ? (string)$this->_anchor : '';
  307. // need basepage for subpages like /Remove (within CreateTOC)
  308. $page = new WikiPageName($this->_page, $this->_basepage, $anchor);
  309. $link = WikiLink($page, 'auto', $label);
  310. return $link->asXML();
  311. }
  312. function asString() {
  313. if (isset($this->_label))
  314. return $this->_label;
  315. return $this->_page;
  316. }
  317. }
  318. class Cached_WikiLinkIfKnown extends Cached_WikiLink
  319. {
  320. function Cached_WikiLinkIfKnown ($moniker) {
  321. $this->_page = $moniker;
  322. }
  323. function expand($basepage, &$markup) {
  324. return WikiLink($this->_page, 'if_known');
  325. }
  326. }
  327. class Cached_PhpwikiURL extends Cached_DynamicContent
  328. {
  329. function Cached_PhpwikiURL ($url, $label) {
  330. $this->_url = $url;
  331. if ($label)
  332. $this->_label = $label;
  333. }
  334. function isInlineElement() {
  335. return true;
  336. }
  337. function expand($basepage, &$markup) {
  338. $label = isset($this->_label) ? $this->_label : false;
  339. return LinkPhpwikiURL($this->_url, $label, $basepage);
  340. }
  341. function asXML() {
  342. $label = isset($this->_label) ? $this->_label : false;
  343. $link = LinkPhpwikiURL($this->_url, $label);
  344. return $link->asXML();
  345. }
  346. function asString() {
  347. if (isset($this->_label))
  348. return $this->_label;
  349. return $this->_url;
  350. }
  351. }
  352. class Cached_ExternalLink extends Cached_Link {
  353. function Cached_ExternalLink($url, $label=false) {
  354. $this->_url = $url;
  355. if ($label && $label != $url)
  356. $this->_label = $label;
  357. }
  358. function _getType() {
  359. return 'external';
  360. }
  361. function _getName($basepage) {
  362. $label = isset($this->_label) ? $this->_label : false;
  363. return ($label and is_string($label)) ? $label : $this->_url;
  364. }
  365. function expand($basepage, &$markup) {
  366. global $request;
  367. $label = isset($this->_label) ? $this->_label : false;
  368. $link = LinkURL($this->_url, $label);
  369. if (GOOGLE_LINKS_NOFOLLOW) {
  370. // Ignores nofollow when the user who saved the page was authenticated.
  371. $page = $request->getPage($basepage);
  372. $current = $page->getCurrentRevision();
  373. if (!$current->get('author_id'))
  374. $link->setAttr('rel', 'nofollow');
  375. }
  376. return $link;
  377. }
  378. function asString() {
  379. if (isset($this->_label))
  380. return $this->_label;
  381. return $this->_url;
  382. }
  383. }
  384. class Cached_InterwikiLink extends Cached_ExternalLink {
  385. function Cached_InterwikiLink($link, $label=false) {
  386. $this->_link = $link;
  387. if ($label)
  388. $this->_label = $label;
  389. }
  390. function _getName($basepage) {
  391. $label = isset($this->_label) ? $this->_label : false;
  392. return ($label and is_string($label)) ? $label : $link;
  393. }
  394. function _getURL($basepage) {
  395. $link = $this->expand($basepage, $this);
  396. return $link->getAttr('href');
  397. }
  398. function expand($basepage, &$markup) {
  399. $intermap = getInterwikiMap();
  400. $label = isset($this->_label) ? $this->_label : false;
  401. return $intermap->link($this->_link, $label);
  402. }
  403. function asString() {
  404. if (isset($this->_label))
  405. return $this->_label;
  406. return $this->_link;
  407. }
  408. }
  409. // Needed to put UserPages to backlinks. Special method to markup userpages with icons
  410. // Thanks to PhpWiki:DanFr for finding this bug.
  411. // Fixed since 1.3.8, prev. versions had no userpages in backlinks
  412. class Cached_UserLink extends Cached_WikiLink {
  413. function expand($basepage, &$markup) {
  414. $label = isset($this->_label) ? $this->_label : false;
  415. $anchor = isset($this->_anchor) ? (string)$this->_anchor : '';
  416. $page = new WikiPageName($this->_page, $basepage, $anchor);
  417. $link = WikiLink($page, 'auto', $label);
  418. // $link = HTML::a(array('href' => $PageName));
  419. $link->setContent(PossiblyGlueIconToText('wikiuser', $this->_page));
  420. $link->setAttr('class', 'wikiuser');
  421. return $link;
  422. }
  423. }
  424. class Cached_PluginInvocation extends Cached_DynamicContent {
  425. function Cached_PluginInvocation ($pi) {
  426. $this->_pi = $pi;
  427. }
  428. function setTightness($top, $bottom) {
  429. $this->_tightenable = 0;
  430. if ($top) $this->_tightenable |= 1;
  431. if ($bottom) $this->_tightenable |= 2;
  432. }
  433. function isInlineElement() {
  434. return false;
  435. }
  436. function expand($basepage, &$markup) {
  437. $loader = $this->_getLoader();
  438. $xml = $loader->expandPI($this->_pi, $GLOBALS['request'], $markup, $basepage);
  439. $div = HTML::div(array('class' => 'plugin'));
  440. if (is_array($plugin_cmdline = $loader->parsePI($this->_pi)) and $plugin_cmdline[1])
  441. $id = GenerateId($plugin_cmdline[1]->getName() . 'Plugin');
  442. if (isset($this->_tightenable)) {
  443. if ($this->_tightenable == 3) {
  444. $span = HTML::span(array('class' => 'plugin'), $xml);
  445. if (!empty($id))
  446. $span->setAttr('id', $id);
  447. return $span;
  448. }
  449. $div->setInClass('tightenable');
  450. $div->setInClass('top', ($this->_tightenable & 1) != 0);
  451. $div->setInClass('bottom', ($this->_tightenable & 2) != 0);
  452. }
  453. if (!empty($id))
  454. $div->setAttr('id', $id);
  455. $div->pushContent($xml);
  456. return $div;
  457. }
  458. function asString() {
  459. return $this->_pi;
  460. }
  461. function getWikiPageLinks($basepage) {
  462. $loader = $this->_getLoader();
  463. return $loader->getWikiPageLinks($this->_pi, $basepage);
  464. }
  465. function & _getLoader() {
  466. static $loader = false;
  467. if (!$loader) {
  468. include_once('lib/WikiPlugin.php');
  469. $loader = new WikiPluginLoader;
  470. }
  471. return $loader;
  472. }
  473. }
  474. // (c-file-style: "gnu")
  475. // Local Variables:
  476. // mode: php
  477. // tab-width: 8
  478. // c-basic-offset: 4
  479. // c-hanging-comment-ender-p: nil
  480. // indent-tabs-mode: nil
  481. // End:
  482. ?>