aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/inc/Ui
diff options
context:
space:
mode:
Diffstat (limited to 'inc/Ui')
-rw-r--r--inc/Ui/Diff.php546
-rw-r--r--inc/Ui/MediaDiff.php339
-rw-r--r--inc/Ui/MediaRevisions.php122
-rw-r--r--inc/Ui/PageConflict.php7
-rw-r--r--inc/Ui/PageDiff.php512
-rw-r--r--inc/Ui/PageDraft.php8
-rw-r--r--inc/Ui/PageRevisions.php181
-rw-r--r--inc/Ui/Revisions.php368
8 files changed, 1361 insertions, 722 deletions
diff --git a/inc/Ui/Diff.php b/inc/Ui/Diff.php
index 513e0667c..eec7c58a1 100644
--- a/inc/Ui/Diff.php
+++ b/inc/Ui/Diff.php
@@ -2,502 +2,168 @@
namespace dokuwiki\Ui;
-use dokuwiki\ChangeLog\PageChangeLog;
-use dokuwiki\ChangeLog\MediaChangeLog;
-use dokuwiki\Extension\Event;
-use dokuwiki\Form\Form;
-
/**
* DokuWiki Diff Interface
+ * parent class of PageDiff and MediaDiff
*
* @package dokuwiki\Ui
*/
-class Diff extends Ui
+abstract class Diff extends Ui
{
- protected $text;
- protected $showIntro;
- protected $difftype;
+ /* @var string */
+ protected $id; // page id or media id
+ protected $item; // page or media
+
+ /* @var int|string */
+ protected $oldRev; // timestamp of older revision, '' means current one
+ protected $newRev; // timestamp of newer revision, '' means current one
+
+ /* @var array */
+ protected $preference = [];
+
+ /* @var ChangeLog */
+ protected $changelog; // PageChangeLog or MediaChangeLog object
/**
* Diff Ui constructor
*
- * @param string $text when non-empty: compare with this text with most current version
- * @param bool $showIntro display the intro text
- * @param string $difftype diff view type (inline or sidebyside)
+ * @param string $id page id or media id
*/
- public function __construct($text = '', $showIntro = true, $difftype = null)
+ public function __construct($id)
{
- $this->text = $text;
- $this->showIntro = $showIntro;
-
- // determine diff view type
- if (isset($difftype)) {
- $this->difftype = $difftype;
- } else {
- global $INPUT;
- global $INFO;
- $this->difftype = $INPUT->str('difftype') ?: get_doku_pref('difftype', $difftype);
- if (empty($this->difftype) && $INFO['ismobile']) {
- $this->difftype = 'inline';
- }
- }
- if ($this->difftype !== 'inline') $this->difftype = 'sidebyside';
+ $this->id = $id;
+ $this->setChangeLog();
}
/**
- * Show diff
- * between current page version and provided $text
- * or between the revisions provided via GET or POST
+ * set class property changelog
+ */
+ abstract protected function setChangeLog();
+
+ /**
+ * item filename resolver
*
- * @author Andreas Gohr <andi@splitbrain.org>
+ * @param string $id page id or media id
+ * @param int|string $rev revision timestamp, or empty string for current one
+ * @return string full path
+ */
+ abstract protected function itemFN($id, $rev = '');
+
+ /**
+ * Set a pair of revisions to be compared
*
- * @return void
+ * @param int $oldRev
+ * @param int $newRev
+ * @return $this
*/
- public function show()
+ public function compare($oldRev, $newRev)
{
- global $ID;
- global $REV;
- global $lang;
- global $INPUT;
- global $INFO;
- $pagelog = new PageChangeLog($ID);
-
- /*
- * Determine requested revision(s)
- */
- // we're trying to be clever here, revisions to compare can be either
- // given as rev and rev2 parameters, with rev2 being optional. Or in an
- // array in rev2.
- $rev1 = $REV;
-
- $rev2 = $INPUT->ref('rev2');
- if (is_array($rev2)) {
- $rev1 = (int) $rev2[0];
- $rev2 = (int) $rev2[1];
-
- if (!$rev1) {
- $rev1 = $rev2;
- unset($rev2);
- }
- } else {
- $rev2 = $INPUT->int('rev2');
- }
-
- /*
- * Determine left and right revision, its texts and the header
- */
- $r_minor = '';
- $l_minor = '';
-
- if ($this->text) { // compare text to the most current revision
- $l_rev = '';
- $l_text = rawWiki($ID, '');
- $l_head = '<a class="wikilink1" href="'. wl($ID) .'">'
- . $ID .' '. dformat((int) @filemtime(wikiFN($ID))) .'</a> '
- . $lang['current'];
-
- $r_rev = '';
- $r_text = cleanText($this->text);
- $r_head = $lang['yours'];
- } else {
- if ($rev1 && isset($rev2) && $rev2) { // two specific revisions wanted
- // make sure order is correct (older on the left)
- if ($rev1 < $rev2) {
- $l_rev = $rev1;
- $r_rev = $rev2;
- } else {
- $l_rev = $rev2;
- $r_rev = $rev1;
- }
- } elseif ($rev1) { // single revision given, compare to current
- $r_rev = '';
- $l_rev = $rev1;
- } else { // no revision was given, compare previous to current
- $r_rev = '';
- $revs = $pagelog->getRevisions(0, 1);
- $l_rev = $revs[0];
- $REV = $l_rev; // store revision back in $REV
- }
-
- // when both revisions are empty then the page was created just now
- if (!$l_rev && !$r_rev) {
- $l_text = '';
- } else {
- $l_text = rawWiki($ID, $l_rev);
- }
- $r_text = rawWiki($ID, $r_rev);
-
- list($l_head, $r_head, $l_minor, $r_minor) = $this->diffHead(
- $l_rev, $r_rev, null, false, ($this->difftype == 'inline')
- );
- }
-
- /*
- * Build navigation
- */
- $l_nav = '';
- $r_nav = '';
- if (!$this->text) {
- list($l_nav, $r_nav) = $this->diffNavigation($pagelog, $l_rev, $r_rev);
- }
- /*
- * Create diff object and the formatter
- */
- $diff = new \Diff(explode("\n", $l_text), explode("\n", $r_text));
-
- if ($this->difftype == 'inline') {
- $diffformatter = new \InlineDiffFormatter();
- } else {
- $diffformatter = new \TableDiffFormatter();
- }
- /*
- * Display intro
- */
- if ($this->showIntro) print p_locale_xhtml('diff');
-
- /*
- * Display type and exact reference
- */
- if (!$this->text) {
- print '<div class="diffoptions group">';
-
- // create the form to select difftype
- $form = new Form(['action' => wl()]);
- $form->setHiddenField('id', $ID);
- $form->setHiddenField('rev2[0]', $l_rev);
- $form->setHiddenField('rev2[1]', $r_rev);
- $form->setHiddenField('do', 'diff');
- $options = array(
- 'sidebyside' => $lang['diff_side'],
- 'inline' => $lang['diff_inline']
- );
- $input = $form->addDropdown('difftype', $options, $lang['diff_type'])
- ->val($this->difftype)->addClass('quickselect');
- $input->useInput(false); // inhibit prefillInput() during toHTML() process
- $form->addButton('do[diff]', 'Go')->attr('type','submit');
- print $form->toHTML();
-
- print '<p>';
- // link to exactly this view FS#2835
- print $this->diffViewlink('difflink', $l_rev, ($r_rev ?: $INFO['currentrev']));
- print '</p>';
-
- print '</div>'; // .diffoptions
- }
-
- /*
- * Display diff view table
- */
- print '<div class="table">';
- print '<table class="diff diff_'. $this->difftype .'">';
-
- //navigation and header
- if ($this->difftype == 'inline') {
- if (!$this->text) {
- print '<tr>'
- . '<td class="diff-lineheader">-</td>'
- . '<td class="diffnav">'. $l_nav .'</td>'
- . '</tr>';
- print '<tr>'
- . '<th class="diff-lineheader">-</th>'
- . '<th '. $l_minor .'>'. $l_head .'</th>'
- .'</tr>';
- }
- print '<tr>'
- . '<td class="diff-lineheader">+</td>'
- . '<td class="diffnav">'. $r_nav .'</td>'
- .'</tr>';
- print '<tr>'
- . '<th class="diff-lineheader">+</th>'
- . '<th '. $r_minor .'>'. $r_head .'</th>'
- . '</tr>';
- } else {
- if (!$this->text) {
- print '<tr>'
- . '<td colspan="2" class="diffnav">'. $l_nav .'</td>'
- . '<td colspan="2" class="diffnav">'. $r_nav .'</td>'
- . '</tr>';
- }
- print '<tr>'
- . '<th colspan="2" '. $l_minor .'>'. $l_head .'</th>'
- . '<th colspan="2" '. $r_minor .'>'. $r_head .'</th>'
- . '</tr>';
- }
-
- //diff view
- print $this->insertSoftbreaks($diffformatter->format($diff));
-
- print '</table>';
- print '</div>';
+ $this->oldRev = $oldRev;
+ $this->newRev = $newRev;
+ return $this;
}
-
/**
- * Get header of diff HTML
+ * Gets or Sets preference of the Ui\Diff object
*
- * @param string $l_rev Left revisions
- * @param string $r_rev Right revision
- * @param string $id Page id, if null $ID is used
- * @param bool $media If it is for media files
- * @param bool $inline Return the header on a single line
- * @return string[] HTML snippets for diff header
+ * @param string|array $prefs a key name or key-value pair(s)
+ * @param mixed $value value used when the first args is string
+ * @return array|$this
*/
- public function diffHead($l_rev, $r_rev, $id = null, $media = false, $inline = false)
+ public function preference($prefs = null, $value = null)
{
- global $lang;
- if ($id === null) {
- global $ID;
- $id = $ID;
- }
- $head_separator = $inline ? ' ' : '<br />';
- $media_or_wikiFN = $media ? 'mediaFN' : 'wikiFN';
- $ml_or_wl = $media ? 'ml' : 'wl';
- $l_minor = $r_minor = '';
-
- if ($media) {
- $changelog = new MediaChangeLog($id);
- } else {
- $changelog = new PageChangeLog($id);
- }
- if (!$l_rev) {
- $l_head = '&mdash;';
- } else {
- $l_info = $changelog->getRevisionInfo($l_rev);
- if ($l_info['user']) {
- $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
- if (auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
- } else {
- $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>';
- }
- $l_user = '<span class="user">'.$l_user.'</span>';
- $l_sum = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : '';
- if ($l_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"';
-
- $l_head_title = ($media) ? dformat($l_rev) : $id.' ['.dformat($l_rev).']';
- $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$l_rev").'">'
- . $l_head_title.'</a></bdi>'.$head_separator.$l_user.' '.$l_sum;
- }
-
- if ($r_rev) {
- $r_info = $changelog->getRevisionInfo($r_rev);
- if ($r_info['user']) {
- $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
- if (auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
- } else {
- $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>';
+ // set
+ if (is_string($prefs) && isset($value)) {
+ $this->preference[$prefs] = $value;
+ return $this;
+ } elseif (is_array($prefs)) {
+ foreach ($prefs as $name => $value) {
+ $this->preference[$name] = $value;
}
- $r_user = '<span class="user">'.$r_user.'</span>';
- $r_sum = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : '';
- if ($r_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
-
- $r_head_title = ($media) ? dformat($r_rev) : $id.' ['.dformat($r_rev).']';
- $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id,"rev=$r_rev").'">'
- . $r_head_title.'</a></bdi>'.$head_separator.$r_user.' '.$r_sum;
- } elseif ($_rev = @filemtime($media_or_wikiFN($id))) {
- $_info = $changelog->getRevisionInfo($_rev);
- if ($_info['user']) {
- $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
- if (auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
- } else {
- $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>';
- }
- $_user = '<span class="user">'.$_user.'</span>';
- $_sum = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : '';
- if ($_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
-
- $r_head_title = ($media) ? dformat($_rev) : $id.' ['.dformat($_rev).']';
- $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($id).'">'
- . $r_head_title.'</a></bdi> '.'('.$lang['current'].')'.$head_separator.$_user.' '.$_sum;
- }else{
- $r_head = '&mdash; ('.$lang['current'].')';
+ return $this;
}
-
- return array($l_head, $r_head, $l_minor, $r_minor);
+ // get
+ return $this->preference;
}
/**
- * Create html for revision navigation
+ * Retrieve requested revision(s) and difftype from Ui\Revisions
*
- * @param PageChangeLog $pagelog changelog object of current page
- * @param int $l_rev left revision timestamp
- * @param int $r_rev right revision timestamp
- * @return string[] html of left and right navigation elements
+ * @return void
*/
- protected function diffNavigation($pagelog, $l_rev, $r_rev)
+ protected function preProcess()
{
- global $INFO, $ID;
-
- // last timestamp is not in changelog, retrieve timestamp from metadata
- // note: when page is removed, the metadata timestamp is zero
- if (!$r_rev) {
- if (isset($INFO['meta']['last_change']['date'])) {
- $r_rev = $INFO['meta']['last_change']['date'];
- } else {
- $r_rev = 0;
- }
- }
-
- //retrieve revisions with additional info
- list($l_revs, $r_revs) = $pagelog->getRevisionsAround($l_rev, $r_rev);
- $l_revisions = array();
- if (!$l_rev) {
- //no left revision given, add dummy
- $l_revisions[0]= array('label' => '', 'attrs' => []);
- }
- foreach ($l_revs as $rev) {
- $info = $pagelog->getRevisionInfo($rev);
- $l_revisions[$rev] = array(
- 'label' => dformat($info['date']) .' '. editorinfo($info['user'], true) .' '. $info['sum'],
- 'attrs' => ['title' => $rev],
- );
- if ($r_rev ? $rev >= $r_rev : false) $l_revisions[$rev]['attrs']['disabled'] = 'disabled';
- }
- $r_revisions = array();
- if (!$r_rev) {
- //no right revision given, add dummy
- $r_revisions[0] = array('label' => '', 'attrs' => []);
- }
- foreach ($r_revs as $rev) {
- $info = $pagelog->getRevisionInfo($rev);
- $r_revisions[$rev] = array(
- 'label' => dformat($info['date']) .' '. editorinfo($info['user'], true) .' '. $info['sum'],
- 'attrs' => ['title' => $rev],
- );
- if ($rev <= $l_rev) $r_revisions[$rev]['attrs']['disabled'] = 'disabled';
- }
+ global $INPUT;
- //determine previous/next revisions
- $l_index = array_search($l_rev, $l_revs);
- $l_prev = $l_index < count($l_revs) - 1 ? $l_revs[$l_index + 1] : null;
- $l_next = $l_index > 1 ? $l_revs[$l_index - 1] : null;
- if ($r_rev) {
- $r_index = array_search($r_rev, $r_revs);
- $r_prev = $r_index < count($r_revs) - 1 ? $r_revs[$r_index + 1] : null;
- $r_next = $r_index > 1 ? $r_revs[$r_index - 1] : null;
- } else {
- //removed page
- if ($l_next) {
- $r_prev = $r_revs[0];
+ // difflink icon click, eg. ?rev=123456789&do=diff
+ if ($INPUT->has('rev')) {
+ $this->oldRev = $INPUT->int('rev');
+ $this->newRev = ''; // current revision
+ }
+
+ // submit button with two checked boxes
+ $rev2 = $INPUT->arr('rev2', []);
+ if (count($rev2) > 1) {
+ if ($rev2[0] == 'current') {
+ [$this->oldRev, $this->newRev] = [$rev2[1], ''];
+ } elseif ($rev2[1] == 'current') {
+ [$this->oldRev, $this->newRev] = [$rev2[0], ''];
+ } elseif ($rev2[0] < $rev2[1]) {
+ [$this->oldRev, $this->newRev] = [$rev2[0], $rev2[1]];
} else {
- $r_prev = null;
+ [$this->oldRev, $this->newRev] = [$rev2[1], $rev2[0]];
}
- $r_next = null;
- }
-
- /*
- * Left side:
- */
- $l_nav = '';
- //move back
- if ($l_prev) {
- $l_nav .= $this->diffViewlink('diffbothprevrev', $l_prev, $r_prev);
- $l_nav .= $this->diffViewlink('diffprevrev', $l_prev, $r_rev);
- }
- //dropdown
- $form = new Form(['action' => wl()]);
- $form->setHiddenField('id', $ID);
- $form->setHiddenField('difftype', $this->difftype);
- $form->setHiddenField('rev2[1]', $r_rev);
- $form->setHiddenField('do', 'diff');
- $input = $form->addDropdown('rev2[0]', $l_revisions)->val($l_rev)->addClass('quickselect');
- $input->useInput(false); // inhibit prefillInput() during toHTML() process
- $form->addButton('do[diff]', 'Go')->attr('type','submit');
- $l_nav .= $form->toHTML();
- //move forward
- if ($l_next && ($l_next < $r_rev || !$r_rev)) {
- $l_nav .= $this->diffViewlink('diffnextrev', $l_next, $r_rev);
}
- /*
- * Right side:
- */
- $r_nav = '';
- //move back
- if ($l_rev < $r_prev) {
- $r_nav .= $this->diffViewlink('diffprevrev', $l_rev, $r_prev);
- }
- //dropdown
- $form = new Form(['action' => wl()]);
- $form->setHiddenField('id', $ID);
- $form->setHiddenField('rev2[0]', $l_rev);
- $form->setHiddenField('difftype', $this->difftype);
- $form->setHiddenField('do', 'diff');
- $input = $form->addDropdown('rev2[1]', $r_revisions)->val($r_rev)->addClass('quickselect');
- $input->useInput(false); // inhibit prefillInput() during toHTML() process
- $form->addButton('do[diff]', 'Go')->attr('type','submit');
- $r_nav .= $form->toHTML();
- //move forward
- if ($r_next) {
- if ($pagelog->isCurrentRevision($r_next)) {
- //last revision is diff with current page
- $r_nav .= $this->diffViewlink('difflastrev', $l_rev);
- } else {
- $r_nav .= $this->diffViewlink('diffnextrev', $l_rev, $r_next);
- }
+ // diff view type
+ if ($INPUT->has('difftype')) {
+ // retrieve requested $difftype
+ $this->preference['difftype'] = $INPUT->str('difftype');
} else {
- $r_nav .= $this->diffViewlink('diffbothnextrev', $l_next, $r_next);
+ // read preference from DokuWiki cookie. PageDiff only
+ $mode = get_doku_pref('difftype', $mode = null);
+ if (isset($mode)) $this->preference['difftype'] = $mode;
}
- return array($l_nav, $r_nav);
}
/**
- * Create html link to a diff view defined by two revisions
+ * get extended revision info
*
- * @param string $linktype
- * @param int $lrev oldest revision
- * @param int $rrev newest revision or null for diff with current revision
- * @return string html of link to a diff view
+ * @param int|string $rev revision identifier, '' means current one
+ * @return array revision info structure of a page or media file
*/
- protected function diffViewlink($linktype, $lrev, $rrev = null)
+ protected function getExtendedRevisionInfo($rev)
{
- global $ID, $lang;
- if ($rrev === null) {
- $urlparam = array(
- 'do' => 'diff',
- 'rev' => $lrev,
- 'difftype' => $this->difftype,
+ $changelog =& $this->changelog;
+
+ if ($rev) {
+ $info = $changelog->getRevisionInfo($rev);
+ } elseif (file_exists($filename = $this->itemFN($this->id))) {
+ $rev = filemtime(fullpath($filename));
+ $info = $changelog->getRevisionInfo($rev) + array(
+ 'current' => true,
);
- } else {
- $urlparam = array(
- 'do' => 'diff',
- 'rev2[0]' => $lrev,
- 'rev2[1]' => $rrev,
- 'difftype' => $this->difftype,
+ } else { // once exists, but now removed
+ $info = array(
+ 'current' => true,
);
}
- return '<a class="'. $linktype .'" href="'. wl($ID, $urlparam) .'" title="'. $lang[$linktype] .'">'
- . '<span>'. $lang[$linktype] .'</span>'
- . '</a>';
+ return array('item' => $this->item) + $info;
}
+
/**
- * Insert soft breaks in diff html
+ * Build header of diff HTML
*
- * @param string $diffhtml
- * @return string
+ * @param string $l_rev Left revisions
+ * @param string $r_rev Right revision
+ * @return string[] HTML snippets for diff header
+ * @deprecated 2020-12-31
*/
- public function insertSoftbreaks($diffhtml)
+ public function buildDiffHead($l_rev, $r_rev)
{
- // search the diff html string for both:
- // - html tags, so these can be ignored
- // - long strings of characters without breaking characters
- return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/', function ($match) {
- // if match is an html tag, return it intact
- if ($match[0][0] == '<') return $match[0];
- // its a long string without a breaking character,
- // make certain characters into breaking characters by inserting a
- // word break opportunity (<wbr> tag) in front of them.
- $regex = <<< REGEX
-(?(?= # start a conditional expression with a positive look ahead ...
-&\#?\\w{1,6};) # ... for html entities - we don't want to split them (ok to catch some invalid combinations)
-&\#?\\w{1,6}; # yes pattern - a quicker match for the html entity, since we know we have one
-|
-[?/,&\#;:] # no pattern - any other group of 'special' characters to insert a breaking character after
-)+ # end conditional expression
-REGEX;
- return preg_replace('<'.$regex.'>xu', '\0<wbr>', $match[0]);
- }, $diffhtml);
+ dbg_deprecated('not used see '. \dokuwiki\Ui\PageDiff::class .'::show()');
}
}
diff --git a/inc/Ui/MediaDiff.php b/inc/Ui/MediaDiff.php
new file mode 100644
index 000000000..5ed46988e
--- /dev/null
+++ b/inc/Ui/MediaDiff.php
@@ -0,0 +1,339 @@
+<?php
+
+namespace dokuwiki\Ui;
+
+use dokuwiki\ChangeLog\MediaChangeLog;
+use dokuwiki\Ui\MediaRevisions;
+use dokuwiki\Extension\Event;
+use dokuwiki\Form\Form;
+use JpegMeta;
+
+/**
+ * DokuWiki MediaDiff Interface
+ *
+ * @package dokuwiki\Ui
+ */
+class MediaDiff extends Diff
+{
+ /* @var MediaChangeLog */
+ protected $changelog;
+
+ /**
+ * MediaDiff Ui constructor
+ *
+ * @param string $id media id
+ */
+ public function __construct($id)
+ {
+ if (!isset($id)) {
+ throw new \InvalidArgumentException('media id should not be empty!');
+ }
+ $this->item = 'media';
+
+ // init preference
+ $this->preference['fromAjax'] = false; // see doluwiki\Ajax::callMediadiff()
+ $this->preference['showIntro'] = false;
+ $this->preference['difftype'] = 'both'; // media diff view type: both, opacity or portions
+
+ parent::__construct($id);
+ }
+
+ /** @inheritdoc */
+ protected function setChangeLog()
+ {
+ $this->changelog = new MediaChangeLog($this->id);
+ }
+
+ /** @inheritdoc */
+ protected function itemFN($id, $rev = '')
+ {
+ return mediaFN($id, $rev);
+ }
+
+ /** @inheritdoc */
+ protected function preProcess()
+ {
+ parent::preProcess();
+ if (!isset($this->oldRev, $this->newRev)) {
+ // no revision was given, compare previous to current
+ $revs = $this->changelog->getRevisions(0, 1);
+ $this->oldRev = file_exists(mediaFN($this->id, $revs[0])) ? $revs[0] : '';
+ $this->newRev = '';
+ }
+ }
+
+ /**
+ * Shows difference between two revisions of media
+ *
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ */
+ public function show()
+ {
+ global $conf;
+
+ $ns = getNS($this->id);
+ $auth = auth_quickaclcheck("$ns:*");
+
+ if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return '';
+
+ // determine left and right revision
+ if (!isset($this->oldRev, $this->newRev)) $this->preProcess();
+ [$oldRev, $newRev] = [$this->oldRev, $this->newRev];
+
+ // prepare event data
+ // NOTE: MEDIA_DIFF event does not found in DokuWiki Event List?
+ $data = array();
+ $data[0] = $this->id;
+ $data[1] = $oldRev;
+ $data[2] = $newRev;
+ $data[3] = $ns;
+ $data[4] = $auth; // permission level
+ $data[5] = $this->preference['fromAjax'];
+
+ // trigger event
+ Event::createAndTrigger('MEDIA_DIFF', $data, null, false);
+
+ if (is_array($data) && count($data) === 6) {
+ $this->id = $data[0];
+ $oldRev = $data[1];
+ $newRev = $data[2];
+ $ns = $data[3];
+ $auth = $data[4];
+ $this->preference['fromAjax'] = $data[5];
+ } else {
+ return '';
+ }
+
+ $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev));
+ $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev));
+
+ $is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
+ if ($is_img) {
+ // get image width and height for the mediamanager preview panel
+ $oldRevSize = media_image_preview_size($this->id, $oldRev, $oldRevMeta);
+ $newRevSize = media_image_preview_size($this->id, $newRev, $newRevMeta);
+ // re-check image, ensure minimum image width for showImageDiff()
+ $is_img = ($oldRevSize && $newRevSize && ($oldRevSize[0] >= 30 || $newRevSize[0] >= 30));
+ }
+
+ // determine requested diff view type
+ if (!$is_img) {
+ $this->preference['difftype'] = 'both';
+ }
+
+ // display intro
+ if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
+
+ // print form to choose diff view type
+ if ($is_img && !$this->preference['fromAjax']) {
+ $this->showDiffViewSelector();
+ echo '<div id="mediamanager__diff" >';
+ }
+
+ switch ($this->preference['difftype']) {
+ case 'opacity':
+ case 'portions':
+ $this->showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize);
+ break;
+ case 'both':
+ default:
+ $this->showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth);
+ break;
+ }
+
+ if ($is_img && !$this->preference['fromAjax']) {
+ echo '</div>';
+ }
+ }
+
+ /**
+ * Print form to choose diff view type
+ * the dropdown is to be added through JavaScript, see lib/scripts/media.js
+ */
+ protected function showDiffViewSelector()
+ {
+ echo '<div class="diffoptions group">';
+
+ $form = new Form([
+ 'id' => 'mediamanager__form_diffview',
+ 'action' => media_managerURL([], '&'),
+ 'method' => 'get',
+ 'class' => 'diffView',
+ ]);
+ $form->addTagOpen('div')->addClass('no');
+ $form->setHiddenField('sectok', null);
+ $form->setHiddenField('mediado', 'diff');
+ $form->setHiddenField('rev2[0]', $this->oldRev ?: 'current');
+ $form->setHiddenField('rev2[1]', $this->newRev ?: 'current');
+ $form->addTagClose('div');
+ echo $form->toHTML();
+
+ echo '</div>'; // .diffoptions
+ }
+
+ /**
+ * Prints two images side by side
+ * and slider
+ *
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ *
+ * @param string|int $oldRev revision timestamp, or empty string
+ * @param string|int $newRev revision timestamp, or empty string
+ * @param array $oldRevSize array with width and height
+ * @param array $newRevSize array with width and height
+ * @param string $type diff view type: opacity or portions
+ */
+ protected function showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize, $type = null)
+ {
+ if (!isset($type)) {
+ $type = $this->preference['difftype'];
+ }
+
+ // adjust image width, right side (newer) has priority
+ if ($oldRevSize != $newRevSize) {
+ if ($newRevSize[0] > $oldRevSize[0]) {
+ $oldRevSize = $newRevSize;
+ }
+ }
+
+ $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
+ $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
+
+ // slider
+ echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>';
+
+ // two images in divs
+ echo '<div class="imageDiff '.$type.'">';
+ echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">';
+ echo '<img src="'.$oldRevSrc.'" alt="" />';
+ echo '</div>';
+ echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">';
+ echo '<img src="'.$newRevSrc.'" alt="" />';
+ echo '</div>';
+ echo '</div>';
+ }
+
+ /**
+ * Shows difference between two revisions of media file
+ *
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ *
+ * @param string|int $oldRev revision timestamp, or empty string
+ * @param string|int $newRev revision timestamp, or empty string
+ * @param JpegMeta $oldRevMeta
+ * @param JpegMeta $newRevMeta
+ * @param int $auth permission level
+ */
+ protected function showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth)
+ {
+ global $lang;
+
+ // revison info of older file (left side)
+ $oldRevInfo = $this->getExtendedRevisionInfo($oldRev);
+ // revison info of newer file (right side)
+ $newRevInfo = $this->getExtendedRevisionInfo($newRev);
+
+ // display diff view table
+ echo '<div class="table">';
+ echo '<table>';
+ echo '<tr>';
+ echo '<th>'. $this->revisionTitle($oldRevInfo) .'</th>';
+ echo '<th>'. $this->revisionTitle($newRevInfo) .'</th>';
+ echo '</tr>';
+
+ echo '<tr class="image">';
+ echo '<td>';
+ media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()?
+ echo '</td>';
+
+ echo '<td>';
+ media_preview($this->id, $auth, $newRev, $newRevMeta);
+ echo '</td>';
+ echo '</tr>';
+
+ echo '<tr class="actions">';
+ echo '<td>';
+ media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons()
+ echo '</td>';
+
+ echo '<td>';
+ media_preview_buttons($this->id, $auth, $newRev);
+ echo '</td>';
+ echo '</tr>';
+
+ $l_tags = media_file_tags($oldRevMeta);
+ $r_tags = media_file_tags($newRevMeta);
+ // FIXME r_tags-only stuff
+ foreach ($l_tags as $key => $l_tag) {
+ if ($l_tag['value'] != $r_tags[$key]['value']) {
+ $r_tags[$key]['highlighted'] = true;
+ $l_tags[$key]['highlighted'] = true;
+ } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) {
+ unset($r_tags[$key]);
+ unset($l_tags[$key]);
+ }
+ }
+
+ echo '<tr>';
+ foreach (array($l_tags, $r_tags) as $tags) {
+ echo '<td>';
+
+ echo '<dl class="img_tags">';
+ foreach ($tags as $tag) {
+ $value = cleanText($tag['value']);
+ if (!$value) $value = '-';
+ echo '<dt>'.$lang[$tag['tag'][1]].'</dt>';
+ echo '<dd>';
+ if ($tag['highlighted']) echo '<strong>';
+ if ($tag['tag'][2] == 'date') {
+ echo dformat($value);
+ } else {
+ echo hsc($value);
+ }
+ if ($tag['highlighted']) echo '</strong>';
+ echo '</dd>';
+ }
+ echo '</dl>';
+
+ echo '</td>';
+ }
+ echo '</tr>';
+
+ echo '</table>';
+ echo '</div>';
+ }
+
+ /**
+ * Revision Title for MediaDiff table headline
+ *
+ * @param array $info Revision info structure of a media file
+ * @return string
+ */
+ protected function revisionTitle(array $info)
+ {
+ global $lang, $INFO;
+
+ if (isset($info['date'])) {
+ $rev = $info['date'];
+ $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">'
+ . dformat($rev).'</a></bdi>';
+ } else {
+ $rev = false;
+ $title = '&mdash;';
+ }
+ if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) {
+ $title .= '&nbsp;('.$lang['current'].')';
+ }
+
+ // append separator
+ $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
+
+ // supplement
+ if (isset($info['date'])) {
+ $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info);
+ $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor();
+ }
+ return $title;
+ }
+
+}
diff --git a/inc/Ui/MediaRevisions.php b/inc/Ui/MediaRevisions.php
new file mode 100644
index 000000000..526aa7ae7
--- /dev/null
+++ b/inc/Ui/MediaRevisions.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace dokuwiki\Ui;
+
+use dokuwiki\ChangeLog\MediaChangeLog;
+use dokuwiki\Form\Form;
+
+/**
+ * DokuWiki MediaRevisions Interface
+ *
+ * @package dokuwiki\Ui
+ */
+class MediaRevisions extends Revisions
+{
+ /* @var MediaChangeLog */
+ protected $changelog;
+
+ /**
+ * MediaRevisions Ui constructor
+ *
+ * @param string $id id of media
+ */
+ public function __construct($id)
+ {
+ if (!$id) {
+ throw new \InvalidArgumentException('media id should not be empty!');
+ }
+ $this->item = 'media';
+ parent::__construct($id);
+ }
+
+ /** @inheritdoc */
+ protected function setChangeLog()
+ {
+ $this->changelog = new MediaChangeLog($this->id);
+ }
+
+ /** @inheritdoc */
+ protected function itemFN($id, $rev = '')
+ {
+ return mediaFN($id, $rev);
+ }
+
+ /**
+ * Display a list of Media Revisions in the MediaManager
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ * @author Satoshi Sahara <sahara.satoshi@gmail.com>
+ *
+ * @param int $first skip the first n changelog lines
+ * @return void
+ */
+ public function show($first = 0)
+ {
+ global $lang;
+
+ // get revisions, and set correct pagenation parameters (first, hasNext)
+ if ($first === null) $first = 0;
+ $hasNext = false;
+ $revisions = $this->getRevisions($first, $hasNext);
+
+ // create the form
+ $form = new Form([
+ 'id' => 'page__revisions', // must not be "media__revisions"
+ 'action' => media_managerURL(['image' => $this->id], '&'),
+ 'class' => 'changes',
+ ]);
+ $form->setHiddenField('mediado', 'diff'); // required for media revisions
+ $form->addTagOpen('div')->addClass('no');
+
+ // start listing
+ $form->addTagOpen('ul');
+ foreach ($revisions as $info) {
+ $rev = $info['date'];
+ $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
+ $form->addTagOpen('li')->addClass($class);
+ $form->addTagOpen('div')->addClass('li');
+
+ if (isset($info['current'])) {
+ $form->addCheckbox('rev2[]')->val('current');
+ } elseif (file_exists(mediaFN($this->id, $rev))) {
+ $form->addCheckbox('rev2[]')->val($rev);
+ } else {
+ $form->addCheckbox('')->val($rev)->attr('disabled','disabled');
+ }
+ $form->addHTML(' ');
+
+ $objRevInfo = $this->getObjRevInfo($info);
+ $html = implode(' ', [
+ $objRevInfo->editDate(), // edit date and time
+ $objRevInfo->difflink(), // link to diffview icon
+ $objRevInfo->itemName(), // name of page or media
+ '<div>',
+ $objRevInfo->editSummary(), // edit summary
+ $objRevInfo->editor(), // editor info
+ $objRevInfo->sizechange(), // size change indicator
+ $objRevInfo->currentIndicator(), // current indicator (only when k=1)
+ '</div>',
+ ]);
+ $form->addHTML($html);
+
+ $form->addTagClose('div');
+ $form->addTagClose('li');
+ }
+ $form->addTagClose('ul'); // end of revision list
+
+ // show button for diff view
+ $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
+
+ $form->addTagClose('div'); // close div class=no
+
+ print $form->toHTML('Revisions');
+
+ // provide navigation for pagenated revision list (of pages and/or media files)
+ print $this->navigation($first, $hasNext, function ($n) {
+ return media_managerURL(['first' => $n], '&', false, true);
+ });
+ }
+
+}
diff --git a/inc/Ui/PageConflict.php b/inc/Ui/PageConflict.php
index fcab37e8f..584860100 100644
--- a/inc/Ui/PageConflict.php
+++ b/inc/Ui/PageConflict.php
@@ -35,7 +35,7 @@ class PageConflict extends Ui
*/
public function show()
{
- global $ID;
+ global $INFO;
global $lang;
// print intro
@@ -44,7 +44,7 @@ class PageConflict extends Ui
// create the form
$form = new Form(['id' => 'dw__editform']);
$form->addTagOpen('div')->addClass('no');
- $form->setHiddenField('id', $ID);
+ $form->setHiddenField('id', $INFO['id']);
$form->setHiddenField('wikitext', $this->text);
$form->setHiddenField('summary', $this->summary);
@@ -56,7 +56,8 @@ class PageConflict extends Ui
print '<br /><br /><br /><br />';
- (new Diff($this->text, false))->show();
+ // print difference
+ (new PageDiff($INFO['id']))->compareWith($this->text)->preference('showIntro', false)->show();
}
}
diff --git a/inc/Ui/PageDiff.php b/inc/Ui/PageDiff.php
new file mode 100644
index 000000000..34be84444
--- /dev/null
+++ b/inc/Ui/PageDiff.php
@@ -0,0 +1,512 @@
+<?php
+
+namespace dokuwiki\Ui;
+
+use dokuwiki\ChangeLog\PageChangeLog;
+use dokuwiki\Ui\PageRevisions;
+use dokuwiki\Form\Form;
+
+/**
+ * DokuWiki PageDiff Interface
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Satoshi Sahara <sahara.satoshi@gmail.com>
+ * @package dokuwiki\Ui
+ */
+class PageDiff extends Diff
+{
+ /* @var PageChangeLog */
+ protected $changelog;
+
+ /* @var string */
+ protected $text;
+
+ /**
+ * PageDiff Ui constructor
+ *
+ * @param string $id page id
+ */
+ public function __construct($id = null)
+ {
+ global $INFO;
+ if (!isset($id)) $id = $INFO['id'];
+ $this->item = 'page';
+
+ // init preference
+ $this->preference['showIntro'] = true;
+ $this->preference['difftype'] = 'sidebyside'; // diff view type: inline or sidebyside
+
+ parent::__construct($id);
+ }
+
+ /** @inheritdoc */
+ protected function setChangeLog()
+ {
+ $this->changelog = new PageChangeLog($this->id);
+ }
+
+ /** @inheritdoc */
+ protected function itemFN($id, $rev = '')
+ {
+ return wikiFN($id, $rev);
+ }
+
+ /**
+ * Set text to be compared with most current version
+ * exclusively use of the compare($old, $new) method
+ *
+ * @param string $text
+ * @return $this
+ */
+ public function compareWith($text = null)
+ {
+ if (isset($text)) {
+ $this->text = $text;
+ $this->oldRev = '';
+ $this->newRev = null;
+ }
+ return $this;
+ }
+
+ /** @inheritdoc */
+ protected function preProcess()
+ {
+ parent::preProcess();
+ if (!isset($this->oldRev, $this->newRev)) {
+ // no revision was given, compare previous to current
+ $this->oldRev = $this->changelog->getRevisions(0, 1)[0];
+ $this->newRev = '';
+
+ global $INFO, $REV;
+ if ($this->id == $INFO['id'])
+ $REV = $this->oldRev; // store revision back in $REV
+ }
+ }
+
+ /**
+ * Show diff
+ * between current page version and provided $text
+ * or between the revisions provided via GET or POST
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ *
+ * @return void
+ */
+ public function show()
+ {
+ global $INFO, $lang;
+
+ // determine left and right revision
+ if (!isset($this->oldRev)) $this->preProcess();
+
+ // create difference engine object
+ if (isset($this->text)) { // compare text to the most current revision
+ $oldText = rawWiki($this->id, '');
+ $newText = cleanText($this->text);
+ } else {
+ // when both revisions are empty then the page was created just now
+ $oldText = (!$this->oldRev && !$this->newRev) ? '' : rawWiki($this->id, $this->oldRev);
+ $newText = rawWiki($this->id, $this->newRev); // empty when removed page
+ }
+ $Difference = new \Diff(explode("\n", $oldText), explode("\n", $newText));
+
+ // revison info of older page (left side)
+ $oldRevInfo = $this->getExtendedRevisionInfo($this->oldRev);
+
+ // revison info of newer page (right side)
+ if (isset($this->text)) {
+ $newRevInfo = array('date' => null);
+ } else {
+ $newRevInfo = $this->getExtendedRevisionInfo($this->newRev);
+ }
+
+ // determin exact revision identifiers, even for current page
+ $oldRev = $oldRevInfo['date'];
+ $newRev = $newRevInfo['date'];
+
+ // build paired navigation
+ $navOlderRevisions = '';
+ $navNewerRevisions = '';
+ if (!isset($this->text)) {
+ list(
+ $navOlderRevisions,
+ $navNewerRevisions,
+ ) = $this->buildRevisionsNavigation($oldRev, $newRev);
+ }
+
+ // display intro
+ if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
+
+ // print form to choose diff view type, and exact url reference to the view
+ if (!isset($this->text)) {
+ $this->showDiffViewSelector($oldRev, $newRev);
+ }
+
+ // assign minor edit checker to the variable
+ $classEditType = function ($info) {
+ return ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? ' class="minor"' : '';
+ };
+
+ // display diff view table
+ echo '<div class="table">';
+ echo '<table class="diff diff_'.$this->preference['difftype'] .'">';
+
+ //navigation and header
+ switch ($this->preference['difftype']) {
+ case 'inline':
+ if (!isset($this->text)) {
+ echo '<tr>'
+ .'<td class="diff-lineheader">-</td>'
+ .'<td class="diffnav">'. $navOlderRevisions .'</td>'
+ .'</tr>';
+ echo '<tr>'
+ .'<th class="diff-lineheader">-</th>'
+ .'<th'.$classEditType($oldRevInfo).'>'.$this->revisionTitle($oldRevInfo).'</th>'
+ .'</tr>';
+ }
+ echo '<tr>'
+ .'<td class="diff-lineheader">+</td>'
+ .'<td class="diffnav">'. $navNewerRevisions .'</td>'
+ .'</tr>';
+ echo '<tr>'
+ .'<th class="diff-lineheader">+</th>'
+ .'<th'.$classEditType($newRevInfo).'>'.$this->revisionTitle($newRevInfo).'</th>'
+ .'</tr>';
+ // create formatter object
+ $DiffFormatter = new \InlineDiffFormatter();
+ break;
+
+ case 'sidebyside':
+ default:
+ if (!isset($this->text)) {
+ echo '<tr>'
+ .'<td colspan="2" class="diffnav">'. $navOlderRevisions .'</td>'
+ .'<td colspan="2" class="diffnav">'. $navNewerRevisions .'</td>'
+ .'</tr>';
+ }
+ echo '<tr>'
+ .'<th colspan="2"'.$classEditType($oldRevInfo).'>'.$this->revisionTitle($oldRevInfo).'</th>'
+ .'<th colspan="2"'.$classEditType($newRevInfo).'>'.$this->revisionTitle($newRevInfo).'</th>'
+ .'</tr>';
+ // create formatter object
+ $DiffFormatter = new \TableDiffFormatter();
+ break;
+ }
+
+ // output formatted difference
+ echo $this->insertSoftbreaks($DiffFormatter->format($Difference));
+
+ echo '</table>';
+ echo '</div>';
+ }
+
+ /**
+ * Revision Title for PageDiff table headline
+ *
+ * @param array $info Revision info structure of a page
+ * @return string
+ */
+ protected function revisionTitle(array $info)
+ {
+ global $lang, $INFO;
+
+ // use designated title when compare current page source with given text
+ if (array_key_exists('date', $info) && is_null($info['date'])) {
+ return $lang['yours'];
+ }
+
+ if (isset($info['date'])) {
+ $rev = $info['date'];
+ $title = '<bdi><a class="wikilink1" href="'.wl($this->id, ['rev' => $rev]).'">'
+ . $this->id.' ['.dformat($rev).']'.'</a></bdi>';
+ } else {
+ $rev = false;
+ $title = '&mdash;';
+ }
+ if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) {
+ $title .= '&nbsp;('.$lang['current'].')';
+ }
+
+ // append separator
+ $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
+
+ // supplement
+ if (isset($info['date'])) {
+ $objRevInfo = (new PageRevisions($this->id))->getObjRevInfo($info);
+ $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor();
+ }
+ return $title;
+ }
+
+ /**
+ * Print form to choose diff view type, and exact url reference to the view
+ *
+ * @param int $oldRev timestamp of older revision, left side
+ * @param int $newRev timestamp of newer revision, right side
+ */
+ protected function showDiffViewSelector($oldRev, $newRev)
+ {
+ global $lang;
+
+ echo '<div class="diffoptions group">';
+
+ // create the form to select difftype
+ $form = new Form(['action' => wl()]);
+ $form->setHiddenField('id', $this->id);
+ $form->setHiddenField('rev2[0]', $this->oldRev ?: 'current');
+ $form->setHiddenField('rev2[1]', $this->newRev ?: 'current');
+ $form->setHiddenField('do', 'diff');
+ $options = array(
+ 'sidebyside' => $lang['diff_side'],
+ 'inline' => $lang['diff_inline'],
+ );
+ $input = $form->addDropdown('difftype', $options, $lang['diff_type'])
+ ->val($this->preference['difftype'])
+ ->addClass('quickselect');
+ $input->useInput(false); // inhibit prefillInput() during toHTML() process
+ $form->addButton('do[diff]', 'Go')->attr('type','submit');
+ echo $form->toHTML();
+
+ // show exact url reference to the view when it is meaningful
+ echo '<p>';
+ if (!isset($this->text) && $oldRev && $newRev) {
+ // link to exactly this view FS#2835
+ $viewUrl = $this->diffViewlink('difflink', $oldRev, $newRev);
+ }
+ echo $viewUrl ?? '<br />';
+ echo '</p>';
+
+ echo '</div>'; // .diffoptions
+ }
+
+ /**
+ * Create html for revision navigation
+ *
+ * The navigation consists of older and newer revisions selectors, each
+ * state mutually depends on the selected revision of opposite side.
+ *
+ * @param int $oldRev timestamp of older revision, older side
+ * @param int $newRev timestamp of newer revision, newer side
+ * @return string[] html of navigation for both older and newer sides
+ */
+ protected function buildRevisionsNavigation($oldRev, $newRev)
+ {
+ global $INFO;
+
+ $changelog =& $this->changelog;
+
+ // determine the last revision, which is usually the timestamp of current page,
+ // however which might be the last revision if the page had removed.
+ if (!$newRev) {
+ if ($this->id == $INFO['id']) {
+ // note: when page is removed, the metadata timestamp is zero
+ $lastRev = $INFO['currentrev'] ?? $INFO['meta']['last_change']['date'] ?? 0;
+ } else {
+ $lastRevs = $changelog->getRevisions(-1, 1) // empty array for removed page
+ ?: $changelog->getRevisions(0, 1); // last entry of changelog
+ $lastRev = count($lastRevs) > 0 ? $lastRevs[0] : 0;
+ }
+ $newRev = $lastRev;
+ }
+
+ // retrieve revisions with additional info
+ list($oldRevs, $newRevs) = $changelog->getRevisionsAround($oldRev, $newRev);
+
+ // build options for dropdown selector
+ $olderRevisions = $this->buildRevisionOptions('older', $oldRevs, $oldRev, $newRev);
+ $newerRevisions = $this->buildRevisionOptions('newer', $newRevs, $oldRev, $newRev);
+
+ //determine previous/next revisions
+ $index = array_search($oldRev, $oldRevs);
+ $oldPrevRev = $oldRevs[$index + 1];
+ $oldNextRev = $oldRevs[$index - 1];
+ if ($newRev) {
+ $index = array_search($newRev, $newRevs);
+ $newPrevRev = $newRevs[$index + 1];
+ $newNextRev = $newRevs[$index - 1];
+ } else {
+ //removed page
+ $newPrevRev = ($oldNextRev) ? $newRevs[0] : null;
+ $newNextRev = null;
+ }
+
+ /*
+ * navigation UI for older revisions / Left side:
+ */
+ $navOlderRevs = '';
+ //move back
+ if ($oldPrevRev) {
+ $navOlderRevs .= $this->diffViewlink('diffbothprevrev', $oldPrevRev, $newPrevRev);
+ $navOlderRevs .= $this->diffViewlink('diffprevrev', $oldPrevRev, $newRev);
+ }
+ //dropdown
+ $navOlderRevs .= $this->buildDropdownSelector('older', $olderRevisions, $oldRev, $newRev);
+ //move forward
+ if ($oldNextRev && ($oldNextRev < $newRev || !$newRev)) {
+ $navOlderRevs .= $this->diffViewlink('diffnextrev', $oldNextRev, $newRev);
+ }
+
+ /*
+ * navigation UI for newer revisions / Right side:
+ */
+ $navNewerRevs = '';
+ //move back
+ if ($oldRev < $newPrevRev) {
+ $navNewerRevs .= $this->diffViewlink('diffprevrev', $oldRev, $newPrevRev);
+ }
+ //dropdown
+ $navNewerRevs .= $this->buildDropdownSelector('newer', $newerRevisions, $oldRev, $newRev);
+ //move forward
+ if ($newNextRev) {
+ if ($changelog->isCurrentRevision($newNextRev)) {
+ //last revision is diff with current page
+ $navNewerRevs .= $this->diffViewlink('difflastrev', $oldRev);
+ } else {
+ $navNewerRevs .= $this->diffViewlink('diffnextrev', $oldRev, $newNextRev);
+ }
+ $navNewerRevs .= $this->diffViewlink('diffbothnextrev', $oldNextRev, $newNextRev);
+ }
+ return array($navOlderRevs, $navNewerRevs);
+ }
+
+ /**
+ * prepare options for dropdwon selector
+ *
+ * @params string $side "older" or "newer"
+ * @params array $revs list of revsion
+ * @param int $oldRev timestamp of older revision, left side
+ * @param int $newRev timestamp of newer revision, right side
+ * @return array
+ */
+ protected function buildRevisionOptions($side, $revs, $oldRev, $newRev)
+ {
+ $changelog =& $this->changelog;
+ $revisions = array();
+
+ if (($side == 'older' && !$oldRev) // NOTE: this case should not happen!
+ ||($side == 'newer' && (!$newRev || !page_exists($this->id)))
+ ) {
+ //no revision given, likely removed page, add dummy entry
+ $revisions['current'] = array(
+ 'label' => '—', // U+2014 &mdash;
+ 'attrs' => [],
+ );
+ }
+
+ foreach ($revs as $rev) {
+ $info = $changelog->getRevisionInfo($rev);
+ $revisions[$rev] = array(
+ 'label' => implode(' ', [
+ dformat($info['date']),
+ editorinfo($info['user'], true),
+ $info['sum'],
+ ]),
+ 'attrs' => ['title' => $rev],
+ );
+ if (($side == 'older' && ($newRev ? $rev >= $newRev : false))
+ ||($side == 'newer' && ($rev <= $oldRev))
+ ) {
+ $revisions[$rev]['attrs']['disabled'] = 'disabled';
+ }
+ }
+ return $revisions;
+ }
+
+ /**
+ * build Dropdown form for revisions navigation
+ *
+ * @params string $side "older" or "newer"
+ * @params array $options dropdown options
+ * @param int $oldRev timestamp of older revision, left side
+ * @param int $newRev timestamp of newer revision, right side
+ * @return sting
+ */
+ protected function buildDropdownSelector($side, $options, $oldRev, $newRev)
+ {
+ $form = new Form(['action' => wl($this->id)]);
+ $form->setHiddenField('id', $this->id);
+ $form->setHiddenField('do', 'diff');
+ $form->setHiddenField('difftype', $this->preference['difftype']);
+
+ switch ($side) {
+ case 'older': // left side
+ $form->setHiddenField('rev2[1]', $newRev ?: 'current');
+ $input = $form->addDropdown('rev2[0]', $options)
+ ->val($oldRev ?: 'current')->addClass('quickselect');
+ $input->useInput(false); // inhibit prefillInput() during toHTML() process
+ break;
+ case 'newer': // right side
+ $form->setHiddenField('rev2[0]', $oldRev ?: 'current');
+ $input = $form->addDropdown('rev2[1]', $options)
+ ->val($newRev ?: 'current')->addClass('quickselect');
+ $input->useInput(false); // inhibit prefillInput() during toHTML() process
+ break;
+ }
+ $form->addButton('do[diff]', 'Go')->attr('type','submit');
+ return $form->toHTML();
+ }
+
+ /**
+ * Create html link to a diff view defined by two revisions
+ *
+ * @param string $linktype
+ * @param int $oldRev older revision
+ * @param int $newRev newer revision or null for diff with current revision
+ * @return string html of link to a diff view
+ */
+ protected function diffViewlink($linktype, $oldRev, $newRev = null)
+ {
+ global $lang;
+ if ($newRev === null) {
+ $urlparam = array(
+ 'do' => 'diff',
+ 'rev' => $oldRev,
+ 'difftype' => $this->preference['difftype'],
+ );
+ } else {
+ $urlparam = array(
+ 'do' => 'diff',
+ 'rev2[0]' => $oldRev,
+ 'rev2[1]' => $newRev,
+ 'difftype' => $this->preference['difftype'],
+ );
+ }
+ $attr = array(
+ 'class' => $linktype,
+ 'href' => wl($this->id, $urlparam, true, '&'),
+ 'title' => $lang[$linktype],
+ );
+ return '<a '. buildAttributes($attr) .'><span>'. $lang[$linktype] .'</span></a>';
+ }
+
+
+ /**
+ * Insert soft breaks in diff html
+ *
+ * @param string $diffhtml
+ * @return string
+ */
+ public function insertSoftbreaks($diffhtml)
+ {
+ // search the diff html string for both:
+ // - html tags, so these can be ignored
+ // - long strings of characters without breaking characters
+ return preg_replace_callback('/<[^>]*>|[^<> ]{12,}/', function ($match) {
+ // if match is an html tag, return it intact
+ if ($match[0][0] == '<') return $match[0];
+ // its a long string without a breaking character,
+ // make certain characters into breaking characters by inserting a
+ // word break opportunity (<wbr> tag) in front of them.
+ $regex = <<< REGEX
+(?(?= # start a conditional expression with a positive look ahead ...
+&\#?\\w{1,6};) # ... for html entities - we don't want to split them (ok to catch some invalid combinations)
+&\#?\\w{1,6}; # yes pattern - a quicker match for the html entity, since we know we have one
+|
+[?/,&\#;:] # no pattern - any other group of 'special' characters to insert a breaking character after
+)+ # end conditional expression
+REGEX;
+ return preg_replace('<'.$regex.'>xu', '\0<wbr>', $match[0]);
+ }, $diffhtml);
+ }
+
+}
diff --git a/inc/Ui/PageDraft.php b/inc/Ui/PageDraft.php
index 609ee508d..ac2a63e9c 100644
--- a/inc/Ui/PageDraft.php
+++ b/inc/Ui/PageDraft.php
@@ -22,21 +22,21 @@ class PageDraft extends Ui
public function show()
{
global $INFO;
- global $ID;
global $lang;
- $draft = new \dokuwiki\Draft($ID, $INFO['client']);
+ $draft = new \dokuwiki\Draft($INFO['id'], $INFO['client']);
$text = $draft->getDraftText();
// print intro
print p_locale_xhtml('draft');
- (new Diff($text, false))->show();
+ // print difference
+ (new PageDiff($INFO['id']))->compareWith($text)->preference('showIntro', false)->show();
// create the draft form
$form = new Form(['id' => 'dw__editform']);
$form->addTagOpen('div')->addClass('no');
- $form->setHiddenField('id', $ID);
+ $form->setHiddenField('id', $INFO['id']);
$form->setHiddenField('date', $draft->getDraftDate());
$form->setHiddenField('wikitext', $text);
diff --git a/inc/Ui/PageRevisions.php b/inc/Ui/PageRevisions.php
new file mode 100644
index 000000000..5e633a58e
--- /dev/null
+++ b/inc/Ui/PageRevisions.php
@@ -0,0 +1,181 @@
+<?php
+
+namespace dokuwiki\Ui;
+
+use dokuwiki\ChangeLog\PageChangeLog;
+use dokuwiki\Form\Form;
+
+/**
+ * DokuWiki PageRevisions Interface
+ *
+ * @package dokuwiki\Ui
+ */
+class PageRevisions extends Revisions
+{
+ /* @var PageChangeLog */
+ protected $changelog;
+
+ /**
+ * PageRevisions Ui constructor
+ *
+ * @param string $id id of page
+ */
+ public function __construct($id = null)
+ {
+ global $INFO;
+ if (!isset($id)) $id = $INFO['id'];
+ $this->item = 'page';
+ parent::__construct($id);
+ }
+
+ /** @inheritdoc */
+ protected function setChangeLog()
+ {
+ $this->changelog = new PageChangeLog($this->id);
+ }
+
+ /** @inheritdoc */
+ protected function itemFN($id, $rev = '')
+ {
+ return wikiFN($id, $rev);
+ }
+
+ /**
+ * Display list of old revisions of the page
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ * @author Kate Arzamastseva <pshns@ukr.net>
+ * @author Satoshi Sahara <sahara.satoshi@gmail.com>
+ *
+ * @param int $first skip the first n changelog lines
+ * @return void
+ */
+ public function show($first = 0)
+ {
+ global $lang, $REV;
+
+ // get revisions, and set correct pagenation parameters (first, hasNext)
+ if ($first === null) $first = 0;
+ $hasNext = false;
+ $revisions = $this->getRevisions($first, $hasNext);
+
+ // print intro
+ print p_locale_xhtml('revisions');
+
+ // create the form
+ $form = new Form([
+ 'id' => 'page__revisions',
+ 'class' => 'changes',
+ ]);
+ $form->addTagOpen('div')->addClass('no');
+
+ // start listing
+ $form->addTagOpen('ul');
+ foreach ($revisions as $info) {
+ $rev = $info['date'];
+ $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
+ $form->addTagOpen('li')->addClass($class);
+ $form->addTagOpen('div')->addClass('li');
+
+ if (isset($info['current'])) {
+ $form->addCheckbox('rev2[]')->val('current');
+ } elseif ($rev == $REV) {
+ $form->addCheckbox('rev2[]')->val($rev)->attr('checked','checked');
+ } elseif (page_exists($this->id, $rev)) {
+ $form->addCheckbox('rev2[]')->val($rev);
+ } else {
+ $form->addCheckbox('')->val($rev)->attr('disabled','disabled');
+ }
+ $form->addHTML(' ');
+
+ $objRevInfo = $this->getObjRevInfo($info);
+ $html = implode(' ', [
+ $objRevInfo->editDate(), // edit date and time
+ $objRevInfo->difflink(), // link to diffview icon
+ $objRevInfo->itemName(), // name of page or media
+ $objRevInfo->editSummary(), // edit summary
+ $objRevInfo->editor(), // editor info
+ $objRevInfo->sizechange(), // size change indicator
+ $objRevInfo->currentIndicator(), // current indicator (only when k=1)
+ ]);
+ $form->addHTML($html);
+ $form->addTagClose('div');
+ $form->addTagClose('li');
+ }
+ $form->addTagClose('ul'); // end of revision list
+
+ // show button for diff view
+ $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
+
+ $form->addTagClose('div'); // close div class=no
+
+ print $form->toHTML('Revisions');
+
+ // provide navigation for pagenated revision list (of pages and/or media files)
+ print $this->navigation($first, $hasNext, function ($n) {
+ return array('do' => 'revisions', 'first' => $n);
+ });
+ }
+
+ /**
+ * Get revisions, and set correct pagenation parameters (first, hasNext)
+ *
+ * @param int $first
+ * @param bool $hasNext
+ * @return array revisions to be shown in a pagenated list
+ * @see also https://www.dokuwiki.org/devel:changelog
+ */
+ protected function getRevisions(&$first, &$hasNext)
+ {
+ global $INFO, $conf;
+
+ if ($this->id != $INFO['id']) {
+ return parent::getRevisions($first, $hasNext);
+ }
+
+ $changelog =& $this->changelog;
+
+ $revisions = [];
+
+ /* we need to get one additional log entry to be able to
+ * decide if this is the last page or is there another one.
+ * see also Ui\Recent::getRecents()
+ */
+ $revlist = $changelog->getRevisions($first, $conf['recent'] +1);
+ if (count($revlist) == 0 && $first != 0) {
+ $first = 0;
+ $revlist = $changelog->getRevisions($first, $conf['recent'] +1);
+ }
+ $exists = $INFO['exists'];
+ if ($first == 0 && $exists) {
+ // add current page as revision[0]
+ $revisions[] = array(
+ 'date' => $INFO['lastmod'],
+ 'ip' => null,
+ 'type' => $INFO['meta']['last_change']['type'],
+ 'id' => $INFO['id'],
+ 'user' => $INFO['editor'],
+ 'sum' => $INFO['sum'],
+ 'extra' => null,
+ 'sizechange' => $INFO['meta']['last_change']['sizechange'],
+ 'item' => $this->item,
+ 'current' => true,
+ );
+ }
+
+ // decide if this is the last page or is there another one
+ $hasNext = false;
+ if (count($revlist) > $conf['recent']) {
+ $hasNext = true;
+ array_pop($revlist); // remove one additional log entry
+ }
+
+ // append each revison info array to the revisions
+ foreach ($revlist as $rev) {
+ $revisions[] = $changelog->getRevisionInfo($rev) + array('item' => $this->item);
+ }
+ return $revisions;
+ }
+
+}
diff --git a/inc/Ui/Revisions.php b/inc/Ui/Revisions.php
index c027244f8..ca38a213a 100644
--- a/inc/Ui/Revisions.php
+++ b/inc/Ui/Revisions.php
@@ -2,190 +2,45 @@
namespace dokuwiki\Ui;
-use dokuwiki\ChangeLog\PageChangeLog;
-use dokuwiki\ChangeLog\MediaChangeLog;
-use dokuwiki\Form\Form;
-
/**
* DokuWiki Revisions Interface
+ * parent class of PageRevisions and MediaRevisions
*
* @package dokuwiki\Ui
*/
-class Revisions extends Ui
+abstract class Revisions extends Ui
{
- protected $first;
- protected $media_id;
+ /* @var string */
+ protected $id; // page id or media id
+ protected $item; // page or media
- /**
- * Revisions Ui constructor
- *
- * @param int $first skip the first n changelog lines
- * @param bool|string $media_id id of media, or false for current page
- */
- public function __construct($first = 0, $media_id = false)
- {
- $this->first = $first;
- $this->media_id = $media_id;
- }
+ /* @var ChangeLog */
+ protected $changelog; // PageChangeLog or MediaChangeLog object
/**
- * Display list of old revisions
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Ben Coburn <btcoburn@silicodon.net>
- * @author Kate Arzamastseva <pshns@ukr.net>
- * @author Satoshi Sahara <sahara.satoshi@gmail.com>
+ * Revisions Ui constructor
*
- * @return void
+ * @param string $id page id or media id
*/
- public function show()
+ public function __construct($id)
{
- global $ID;
-
- if ($this->media_id) {
- return $this->showMediaRevisions($this->media_id);
- } else {
- return $this->showPageRevisions($ID);
- }
+ $this->id = $id;
+ $this->setChangeLog();
}
/**
- * Display a list of Media Revisions in the MediaManager
- *
- * @param string $id media id
- * @return void
+ * set class property changelog
*/
- protected function showMediaRevisions($id)
- {
- global $lang;
-
- // get revisions, and set correct pagenation parameters (first, hasNext)
- $first = $this->first;
- $hasNext = false;
- $revisions = $this->getRevisions($first, $hasNext);
-
- // create the form
- $form = new Form([
- 'id' => 'page__revisions', // must not be "media__revisions"
- 'action' => media_managerURL(['image' => $id], '&'),
- 'class' => 'changes',
- ]);
- $form->setHiddenField('mediado', 'diff'); // required for media revisions
- $form->addTagOpen('div')->addClass('no');
-
- // start listing
- $form->addTagOpen('ul');
- foreach ($revisions as $info) {
- $rev = $info['date'];
- $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
- $form->addTagOpen('li')->addClass($class);
- $form->addTagOpen('div')->addClass('li');
-
- if (isset($info['current'])) {
- $form->addCheckbox('rev2[]')->val('current');
- } elseif (file_exists(mediaFN($id, $rev))) {
- $form->addCheckbox('rev2[]')->val($rev);
- } else {
- $form->addCheckbox('')->val($rev)->attr('disabled','disabled');
- }
- $form->addHTML(' ');
-
- $objRevInfo = $this->getObjRevInfo($info);
- $html = implode(' ', [
- $objRevInfo->editDate(), // edit date and time
- $objRevInfo->difflink(), // link to diffview icon
- $objRevInfo->itemName(), // name of page or media
- '<div>',
- $objRevInfo->editSummary(), // edit summary
- $objRevInfo->editor(), // editor info
- html_sizechange($info['sizechange']), // size change indicator
- $objRevInfo->currentIndicator(), // current indicator (only when k=1)
- '</div>',
- ]);
- $form->addHTML($html);
-
- $form->addTagClose('div');
- $form->addTagClose('li');
- }
- $form->addTagClose('ul'); // end of revision list
-
- // show button for diff view
- $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
-
- $form->addTagClose('div'); // close div class=no
-
- print $form->toHTML('Revisions');
-
- // provide navigation for pagenated revision list (of pages and/or media files)
- print $this->htmlNavigation($id, $first, $hasNext);
- }
+ abstract protected function setChangeLog();
/**
- * Display a list of Page Revisions
+ * item filename resolver
*
- * @return void
+ * @param string $id page id or media id
+ * @param int|string $rev revision timestamp, or empty string for current one
+ * @return string full path
*/
- protected function showPageRevisions($id)
- {
- global $lang;
-
- // get revisions, and set correct pagenation parameters (first, hasNext)
- $first = $this->first;
- $hasNext = false;
- $revisions = $this->getRevisions($first, $hasNext);
-
- // print intro
- print p_locale_xhtml('revisions');
-
- // create the form
- $form = new Form([
- 'id' => 'page__revisions',
- 'class' => 'changes',
- ]);
- $form->addTagOpen('div')->addClass('no');
-
- // start listing
- $form->addTagOpen('ul');
- foreach ($revisions as $info) {
- $rev = $info['date'];
- $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
- $form->addTagOpen('li')->addClass($class);
- $form->addTagOpen('div')->addClass('li');
-
- if (page_exists($id, $rev)) {
- $form->addCheckbox('rev2[]')->val($rev);
- } else {
- $form->addCheckbox('')->val($rev)->attr('disabled','disabled');
- }
- $form->addHTML(' ');
-
- $objRevInfo = $this->getObjRevInfo($info);
- $html = implode(' ', [
- $objRevInfo->editDate(), // edit date and time
- $objRevInfo->difflink(), // link to diffview icon
- $objRevInfo->itemName(), // name of page or media
- $objRevInfo->editSummary(), // edit summary
- $objRevInfo->editor(), // editor info
- $objRevInfo->sizechange(), // size change indicator
- $objRevInfo->currentIndicator(), // current indicator (only when k=1)
- ]);
- $form->addHTML($html);
- $form->addTagClose('div');
- $form->addTagClose('li');
- }
- $form->addTagClose('ul'); // end of revision list
-
- // show button for diff view
- $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
-
- $form->addTagClose('div'); // close div class=no
-
- print $form->toHTML('Revisions');
-
- // provide navigation for pagenated revision list (of pages and/or media files)
- print $this->htmlNavigation($id, $first, $hasNext);
- }
-
+ abstract protected function itemFN($id, $rev = '');
/**
* Get revisions, and set correct pagenation parameters (first, hasNext)
@@ -197,15 +52,11 @@ class Revisions extends Ui
*/
protected function getRevisions(&$first, &$hasNext)
{
- global $INFO, $conf;
+ global $conf;
- if ($this->media_id) {
- $changelog = new MediaChangeLog($this->media_id);
- } else {
- $changelog = new PageChangeLog($INFO['id']);
- }
+ $changelog =& $this->changelog;
- $revisions = [];
+ $revisions = array();
/* we need to get one additional log entry to be able to
* decide if this is the last page or is there another one.
@@ -216,46 +67,25 @@ class Revisions extends Ui
$first = 0;
$revlist = $changelog->getRevisions($first, $conf['recent'] +1);
}
- $exists = ($this->media_id) ? file_exists(mediaFN($this->media_id)) : $INFO['exists'];
- if ($first === 0 && $exists) {
- // add current page or media as revision[0]
- if ($this->media_id) {
- $rev = filemtime(fullpath(mediaFN($this->media_id)));
- $changelog->setChunkSize(1024);
- $revinfo = $changelog->getRevisionInfo($rev) ?: array(
- 'date' => $rev,
- 'ip' => null,
- 'type' => null,
- 'id' => $this->media_id,
- 'user' => null,
- 'sum' => null,
- 'extra' => null,
- 'sizechange' => null,
- );
- $revisions[] = $revinfo + array(
- 'media' => true,
- 'current' => true,
- );
- } else {
- if (isset($INFO['meta']['last_change'])) {
- $type = $INFO['meta']['last_change']['type'];
- $sizechange = $INFO['meta']['last_change']['sizechange'];
- } else {
- $type = $sizechange = null;
- }
- $revisions[] = array(
- 'date' => $INFO['lastmod'],
- 'ip' => null,
- 'type' => $type,
- 'id' => $INFO['id'],
- 'user' => $INFO['editor'],
- 'sum' => $INFO['sum'],
- 'extra' => null,
- 'sizechange' => $sizechange,
- 'current' => true,
- );
- }
+ // add current page or media as revision[0] when necessary
+ if ($first === 0 && file_exists($this->itemFN($this->id))) {
+ $rev = filemtime(fullpath($this->itemFN($this->id)));
+ $changelog->setChunkSize(1024); //FIXME why does chunksize change wanted?
+ $revinfo = $changelog->getRevisionInfo($rev) ?: array(
+ 'date' => $rev,
+ 'ip' => null,
+ 'type' => null,
+ 'id' => $this->id,
+ 'user' => null,
+ 'sum' => null,
+ 'extra' => null,
+ 'sizechange' => null,
+ );
+ $revisions[] = $revinfo + array(
+ 'item' => $this->item,
+ 'current' => true,
+ );
}
// decide if this is the last page or is there another one
@@ -267,11 +97,7 @@ class Revisions extends Ui
// append each revison info array to the revisions
foreach ($revlist as $rev) {
- if ($this->media_id) {
- $revisions[] = $changelog->getRevisionInfo($rev) + array('media' => true);
- } else {
- $revisions[] = $changelog->getRevisionInfo($rev);
- }
+ $revisions[] = $changelog->getRevisionInfo($rev) + array('item' => $this->item);
}
return $revisions;
}
@@ -279,12 +105,12 @@ class Revisions extends Ui
/**
* Navigation buttons for Pagenation (prev/next)
*
- * @param string $id page id or media id
* @param int $first
* @param bool $hasNext
+ * @param callable $callback returns array of hidden fields for the form button
* @return array html
*/
- protected function htmlNavigation($id, $first, $hasNext)
+ protected function navigation($first, $hasNext, $callback)
{
global $conf;
@@ -293,20 +119,12 @@ class Revisions extends Ui
if ($first > 0) {
$first = max($first - $conf['recent'], 0);
$html.= '<div class="pagenav-prev">';
- if ($this->media_id) {
- $html.= html_btn('newer', $id, "p", media_managerURL(['first' => $first], '&', false, true));
- } else {
- $html.= html_btn('newer', $id, "p" ,['do' => 'revisions', 'first' => $first]);
- }
+ $html.= html_btn('newer', $this->id, "p", $callback($first));
$html.= '</div>';
}
if ($hasNext) {
$html.= '<div class="pagenav-next">';
- if ($this->media_id) {
- $html.= html_btn('older', $id, "n", media_managerURL(['first' => $last], '&', false, true));
- } else {
- $html.= html_btn('older', $id, "n", ['do' => 'revisions', 'first' => $last]);
- }
+ $html.= html_btn('older', $this->id, "n", $callback($last));
$html.= '</div>';
}
$html.= '</div>';
@@ -319,7 +137,7 @@ class Revisions extends Ui
* @param array $info Revision info structure of a page or media file
* @return objRevInfo object (anonymous class)
*/
- protected function getObjRevInfo(array $info)
+ public function getObjRevInfo(array $info)
{
return new class ($info) // anonymous class (objRevInfo)
{
@@ -377,30 +195,30 @@ class Revisions extends Ui
$id = $this->info['id'];
$rev = $this->info['date'];
- if (isset($this->info['media'])) {
- // media file revision
- if (isset($this->info['current'])) {
- $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view'], '&');
- $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
- } elseif (file_exists(mediaFN($id, $rev))) {
- $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view', 'rev'=> $rev], '&');
- $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
- } else {
- $html = $id;
- }
- return $html;
- } else {
- // page revision
- $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
- if (!$display_name) $display_name = $id;
- if ($this->info['current'] || page_exists($id, $rev)) {
- $href = wl($id, "rev=$rev", false, '&');
- $html = '<a href="'.$href.'" class="wikilink1">'.$display_name.'</a>';
- } else {
- $html = $display_name;
- }
- return $html;
+ switch ($this->info['item']) {
+ case 'media': // media file revision
+ if (isset($this->info['current'])) {
+ $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view'], '&');
+ $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
+ } elseif (file_exists(mediaFN($id, $rev))) {
+ $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view', 'rev'=> $rev], '&');
+ $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
+ } else {
+ $html = $id;
+ }
+ return $html;
+ case 'page': // page revision
+ $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
+ if (!$display_name) $display_name = $id;
+ if ($this->info['current'] || page_exists($id, $rev)) {
+ $href = wl($id, "rev=$rev", false, '&');
+ $html = '<a href="'.$href.'" class="wikilink1">'.$display_name.'</a>';
+ } else {
+ $html = $display_name;
+ }
+ return $html;
}
+ return '';
}
// icon difflink
@@ -410,31 +228,31 @@ class Revisions extends Ui
$id = $this->info['id'];
$rev = $this->info['date'];
- if (isset($this->info['media'])) {
- // media file revision
- if (isset($this->info['current']) || !file_exists(mediaFN($id, $rev))) {
- $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
- } else {
- $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
- $html = '<a href="'.$href.'" class="diff_link">'
- . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
- . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
- . '</a> ';
- }
- return $html;
- } else {
- // page revision
- if ($this->info['current'] || !page_exists($id, $rev)) {
- $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
- } else {
- $href = wl($id, "rev=$rev,do=diff", false, '&');
- $html = '<a href="'.$href.'" class="diff_link">'
- . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
- . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
- . '</a>';
- }
- return $html;
+ switch ($this->info['item']) {
+ case 'media': // media file revision
+ if (isset($this->info['current']) || !file_exists(mediaFN($id, $rev))) {
+ $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
+ } else {
+ $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
+ $html = '<a href="'.$href.'" class="diff_link">'
+ . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
+ . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
+ . '</a> ';
+ }
+ return $html;
+ case 'page': // page revision
+ if ($this->info['current'] || !page_exists($id, $rev)) {
+ $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
+ } else {
+ $href = wl($id, "rev=$rev,do=diff", false, '&');
+ $html = '<a href="'.$href.'" class="diff_link">'
+ . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
+ . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
+ . '</a>';
+ }
+ return $html;
}
+ return '';
}
// size change