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.
 
 
 
 
 

230 lines
7.8 KiB

  1. <?php
  2. namespace dokuwiki\Ui;
  3. use dokuwiki\ChangeLog\MediaChangeLog;
  4. use dokuwiki\ChangeLog\PageChangeLog;
  5. use dokuwiki\ChangeLog\RevisionInfo;
  6. use dokuwiki\Form\Form;
  7. /**
  8. * DokuWiki Recent Interface
  9. *
  10. * @package dokuwiki\Ui
  11. */
  12. class Recent extends Ui
  13. {
  14. protected $first;
  15. protected $show_changes;
  16. /**
  17. * Recent Ui constructor
  18. *
  19. * @param int $first skip the first n changelog lines
  20. * @param string $show_changes type of changes to show; 'pages', 'mediafiles', or 'both'
  21. */
  22. public function __construct($first = 0, $show_changes = 'both')
  23. {
  24. $this->first = $first;
  25. $this->show_changes = $show_changes;
  26. }
  27. /**
  28. * Display recent changes
  29. *
  30. * @return void
  31. * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  32. * @author Ben Coburn <btcoburn@silicodon.net>
  33. * @author Kate Arzamastseva <pshns@ukr.net>
  34. * @author Satoshi Sahara <sahara.satoshi@gmail.com>
  35. *
  36. * @author Andreas Gohr <andi@splitbrain.org>
  37. */
  38. public function show()
  39. {
  40. global $conf, $lang;
  41. global $ID;
  42. // get recent items, and set correct pagination parameters (first, hasNext)
  43. $first = $this->first;
  44. $hasNext = false;
  45. $recents = $this->getRecents($first, $hasNext);
  46. // print intro
  47. echo p_locale_xhtml('recent');
  48. if (getNS($ID) != '') {
  49. echo '<div class="level1"><p>'
  50. . sprintf($lang['recent_global'], getNS($ID), wl('', 'do=recent'))
  51. . '</p></div>';
  52. }
  53. // create the form
  54. $form = new Form(['id' => 'dw__recent', 'method' => 'GET', 'action' => wl($ID), 'class' => 'changes']);
  55. $form->addTagOpen('div')->addClass('no');
  56. $form->setHiddenField('sectok', null);
  57. $form->setHiddenField('do', 'recent');
  58. $form->setHiddenField('id', $ID);
  59. // show dropdown selector, whether include not only recent pages but also recent media files?
  60. if ($conf['mediarevisions']) {
  61. $this->addRecentItemSelector($form);
  62. }
  63. // start listing of recent items
  64. $form->addTagOpen('ul');
  65. foreach ($recents as $recent) {
  66. // check possible external edition for current page or media
  67. $this->checkCurrentRevision($recent);
  68. $RevInfo = new RevisionInfo($recent);
  69. $RevInfo->isCurrent(true);
  70. $class = ($RevInfo->val('type') === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
  71. $form->addTagOpen('li')->addClass($class);
  72. $form->addTagOpen('div')->addClass('li');
  73. $html = implode(' ', [
  74. $RevInfo->showFileIcon(), // filetype icon
  75. $RevInfo->showEditDate(), // edit date and time
  76. $RevInfo->showIconCompareWithPrevious(), // link to diff view icon
  77. $RevInfo->showIconRevisions(), // link to revisions icon
  78. $RevInfo->showFileName(), // name of page or media
  79. $RevInfo->showEditSummary(), // edit summary
  80. $RevInfo->showEditor(), // editor info
  81. $RevInfo->showSizechange(), // size change indicator
  82. ]);
  83. $form->addHTML($html);
  84. $form->addTagClose('div');
  85. $form->addTagClose('li');
  86. }
  87. $form->addTagClose('ul');
  88. $form->addTagClose('div'); // close div class=no
  89. // provide navigation for paginated recent list (of pages and/or media files)
  90. $form->addHTML($this->htmlNavigation($first, $hasNext));
  91. echo $form->toHTML('Recent');
  92. }
  93. /**
  94. * Get recent items, and set correct pagination parameters (first, hasNext)
  95. *
  96. * @param int $first
  97. * @param bool $hasNext
  98. * @return array recent items to be shown in a paginated list
  99. *
  100. * @see also dokuwiki\Changelog::getRevisionInfo()
  101. */
  102. protected function getRecents(&$first, &$hasNext)
  103. {
  104. global $ID, $conf;
  105. $flags = 0;
  106. if ($this->show_changes == 'mediafiles' && $conf['mediarevisions']) {
  107. $flags = RECENTS_MEDIA_CHANGES;
  108. } elseif ($this->show_changes == 'pages') {
  109. $flags = 0;
  110. } elseif ($conf['mediarevisions']) {
  111. $flags = RECENTS_MEDIA_PAGES_MIXED;
  112. }
  113. /* we need to get one additionally log entry to be able to
  114. * decide if this is the last page or is there another one.
  115. * This is the cheapest solution to get this information.
  116. */
  117. $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
  118. if (count($recents) == 0 && $first != 0) {
  119. $first = 0;
  120. $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
  121. }
  122. $hasNext = false;
  123. if (count($recents) > $conf['recent']) {
  124. $hasNext = true;
  125. array_pop($recents); // remove extra log entry
  126. }
  127. return $recents;
  128. }
  129. /**
  130. * Check possible external deletion for current page or media
  131. *
  132. * To keep sort order in the recent list, we ignore externally modification.
  133. * It is not possible to know when external deletion had happened,
  134. * $info['date'] is to be incremented 1 second when such deletion detected.
  135. */
  136. protected function checkCurrentRevision(array &$info)
  137. {
  138. if ($info['mode'] == RevisionInfo::MODE_PAGE) {
  139. $changelog = new PageChangelog($info['id']);
  140. } else {
  141. $changelog = new MediaChangelog($info['id']);
  142. }
  143. if (!$changelog->isCurrentRevision($info['date'])) {
  144. $currentRevInfo = $changelog->getCurrentRevisionInfo();
  145. if ($currentRevInfo['type'] == DOKU_CHANGE_TYPE_DELETE) {
  146. // the page or media file was externally deleted, updated info because the link is already red
  147. // externally created and edited not updated because sorting by date is not worth so much changes
  148. $info = array_merge($info, $currentRevInfo);
  149. }
  150. }
  151. unset($changelog);
  152. }
  153. /**
  154. * Navigation buttons for Pagination (prev/next)
  155. *
  156. * @param int $first
  157. * @param bool $hasNext
  158. * @return string html
  159. */
  160. protected function htmlNavigation($first, $hasNext)
  161. {
  162. global $conf, $lang;
  163. $last = $first + $conf['recent'];
  164. $html = '<div class="pagenav">';
  165. if ($first > 0) {
  166. $first = max($first - $conf['recent'], 0);
  167. $html .= '<div class="pagenav-prev">';
  168. $html .= '<button type="submit" name="first[' . $first . ']" accesskey="n"'
  169. . ' title="' . $lang['btn_newer'] . ' [N]" class="button show">'
  170. . $lang['btn_newer']
  171. . '</button>';
  172. $html .= '</div>';
  173. }
  174. if ($hasNext) {
  175. $html .= '<div class="pagenav-next">';
  176. $html .= '<button type="submit" name="first[' . $last . ']" accesskey="p"'
  177. . ' title="' . $lang['btn_older'] . ' [P]" class="button show">'
  178. . $lang['btn_older']
  179. . '</button>';
  180. $html .= '</div>';
  181. }
  182. $html .= '</div>';
  183. return $html;
  184. }
  185. /**
  186. * Add dropdown selector of item types to the form instance
  187. *
  188. * @param Form $form
  189. * @return void
  190. */
  191. protected function addRecentItemSelector(Form $form)
  192. {
  193. global $lang;
  194. $form->addTagOpen('div')->addClass('changeType');
  195. $options = [
  196. 'pages' => $lang['pages_changes'],
  197. 'mediafiles' => $lang['media_changes'],
  198. 'both' => $lang['both_changes']
  199. ];
  200. $form->addDropdown('show_changes', $options, $lang['changes_type'])
  201. ->val($this->show_changes)->addClass('quickselect');
  202. $form->addButton('do[recent]', $lang['btn_apply'])->attr('type', 'submit');
  203. $form->addTagClose('div');
  204. }
  205. }