You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

216 lines
5.8 KiB

  1. <?php
  2. namespace dokuwiki\Feed;
  3. use Diff;
  4. use dokuwiki\ChangeLog\PageChangeLog;
  5. use TableDiffFormatter;
  6. use UnifiedDiffFormatter;
  7. /**
  8. * Accept more or less arbitrary data to represent a page and provide lazy loading accessors
  9. * to all the data we need for feed generation.
  10. */
  11. class FeedPageProcessor extends FeedItemProcessor
  12. {
  13. /** @var array[] metadata */
  14. protected $meta;
  15. // region data processors
  16. /** @inheritdoc */
  17. public function getURL($linkto)
  18. {
  19. switch ($linkto) {
  20. case 'page':
  21. $opt = ['rev' => $this->getRev()];
  22. break;
  23. case 'rev':
  24. $opt = ['rev' => $this->getRev(), 'do' => 'revisions'];
  25. break;
  26. case 'current':
  27. $opt = [];
  28. break;
  29. case 'diff':
  30. default:
  31. $opt = ['rev' => $this->getRev(), 'do' => 'diff'];
  32. }
  33. return wl($this->getId(), $opt, true, '&');
  34. }
  35. /** @inheritdoc */
  36. public function getBody($content)
  37. {
  38. global $lang;
  39. switch ($content) {
  40. case 'diff':
  41. $diff = $this->getDiff();
  42. // note: diff output must be escaped, UnifiedDiffFormatter provides plain text
  43. $udf = new UnifiedDiffFormatter();
  44. return "<pre>\n" . hsc($udf->format($diff)) . "\n</pre>";
  45. case 'htmldiff':
  46. $diff = $this->getDiff();
  47. // note: no need to escape diff output, TableDiffFormatter provides 'safe' html
  48. $tdf = new TableDiffFormatter();
  49. $content = '<table>';
  50. $content .= '<tr><th colspan="2" width="50%">' . dformat($this->getPrev()) . '</th>';
  51. $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>';
  52. $content .= $tdf->format($diff);
  53. $content .= '</table>';
  54. return $content;
  55. case 'html':
  56. if ($this->isExisting()) {
  57. $html = p_wiki_xhtml($this->getId(), '', false);
  58. } else {
  59. $html = p_wiki_xhtml($this->getId(), $this->getRev(), false);
  60. }
  61. return $this->cleanHTML($html);
  62. case 'abstract':
  63. default:
  64. return $this->getAbstract();
  65. }
  66. }
  67. /** @inheritdoc */
  68. public function getCategory()
  69. {
  70. $meta = $this->getMetaData();
  71. return (array)($meta['subject'] ?? (string)getNS($this->getId()));
  72. }
  73. // endregion
  74. // region data accessors
  75. /**
  76. * Get the page abstract
  77. *
  78. * @return string
  79. */
  80. public function getAbstract()
  81. {
  82. if (!isset($this->data['abstract'])) {
  83. $meta = $this->getMetaData();
  84. if (isset($meta['description']['abstract'])) {
  85. $this->data['abstract'] = (string)$meta['description']['abstract'];
  86. } else {
  87. $this->data['abstract'] = '';
  88. }
  89. }
  90. return $this->data['abstract'];
  91. }
  92. /** @inheritdoc */
  93. public function getRev()
  94. {
  95. $rev = parent::getRev();
  96. if ($rev) return $rev;
  97. if (page_exists($this->id)) {
  98. $this->data['rev'] = filemtime(wikiFN($this->id));
  99. $this->data['exists'] = true;
  100. } else {
  101. $this->loadRevisions();
  102. }
  103. return $this->data['rev'];
  104. }
  105. /**
  106. * Get the previous revision timestamp of this page
  107. *
  108. * @return int|null The previous revision or null if there is none
  109. */
  110. public function getPrev()
  111. {
  112. if ($this->data['prev'] ?? 0) return $this->data['prev'];
  113. $this->loadRevisions();
  114. return $this->data['prev'];
  115. }
  116. /**
  117. * Does this page exist?
  118. *
  119. * @return bool
  120. */
  121. public function isExisting()
  122. {
  123. if (!isset($this->data['exists'])) {
  124. $this->data['exists'] = page_exists($this->id);
  125. }
  126. return $this->data['exists'];
  127. }
  128. /**
  129. * Get the title of this page
  130. *
  131. * @return string
  132. */
  133. public function getTitle()
  134. {
  135. global $conf;
  136. if (!isset($this->data['title'])) {
  137. if ($conf['useheading']) {
  138. $this->data['title'] = p_get_first_heading($this->id);
  139. } else {
  140. $this->data['title'] = noNS($this->id);
  141. }
  142. }
  143. return $this->data['title'];
  144. }
  145. // endregion
  146. /**
  147. * Get the metadata of this page
  148. *
  149. * @return array[]
  150. */
  151. protected function getMetaData()
  152. {
  153. if (!isset($this->meta)) {
  154. $this->meta = (array)p_get_metadata($this->id);
  155. }
  156. return $this->meta;
  157. }
  158. /**
  159. * Load the current and previous revision from the changelog
  160. * @return void
  161. */
  162. protected function loadRevisions()
  163. {
  164. $changelog = new PageChangeLog($this->id);
  165. $revs = $changelog->getRevisions(0, 2); // FIXME check that this returns the current one correctly
  166. if (!isset($this->data['rev'])) {
  167. // prefer an already set date, only set if missing
  168. // it should usally not happen that neither is available
  169. $this->data['rev'] = $revs[0] ?? 0;
  170. }
  171. // a previous revision might not exist
  172. $this->data['prev'] = $revs[1] ?? null;
  173. }
  174. /**
  175. * Get a diff between this and the previous revision
  176. *
  177. * @return Diff
  178. */
  179. protected function getDiff()
  180. {
  181. $prev = $this->getPrev();
  182. if ($prev) {
  183. return new Diff(
  184. explode("\n", rawWiki($this->getId(), $prev)),
  185. explode("\n", rawWiki($this->getId(), ''))
  186. );
  187. }
  188. return new Diff([''], explode("\n", rawWiki($this->getId(), '')));
  189. }
  190. }