xref: /dokuwiki/inc/Ui/Diff.php (revision 8068440f5f0623dc6322b168a36e3958883e9ba1)
1<?php
2
3namespace dokuwiki\Ui;
4
5use dokuwiki\ChangeLog\PageChangeLog;
6use dokuwiki\ChangeLog\MediaChangeLog;
7
8/**
9 * DokuWiki Diff Interface
10 * parent class of PageDiff and MediaDiff
11 *
12 * @package dokuwiki\Ui
13 */
14abstract class Diff extends Ui
15{
16    /* @var string */
17    protected $id;  // page id or media id
18
19    /* @var int */
20    protected $old_rev; // older revision, timestamp of left side
21    protected $new_rev; // newer revision, timestamp of right side
22
23    /* @var array */
24    protected $preference = [];
25
26    /* @var ChangeLog */
27    protected $changelog; // PageChangeLog or MediaChangeLog object
28
29    /**
30     * Diff Ui constructor
31     *
32     * @param string $id  page id or media id
33     */
34    public function __construct($id)
35    {
36        $this->id = $id;
37        $this->setChangeLog();
38    }
39
40    /**
41     * set class property changelog
42     */
43    abstract protected function setChangeLog();
44
45    /**
46     * Set a pair of revisions to be compared
47     *
48     * @param int $old_rev
49     * @param int $new_rev
50     * @return $this
51     */
52    public function compare($old_rev, $new_rev)
53    {
54        $this->old_rev = $old_rev;
55        $this->new_rev = $new_rev;
56        return $this;
57    }
58
59    /**
60     * Gets or Sets preference of the Ui\Diff object
61     *
62     * @param string|array $prefs  a key name or key-value pair(s)
63     * @param mixed $value         value used when the first args is string
64     * @return array|$this
65     */
66    public function preference($prefs = null, $value = null)
67    {
68        // set
69        if (is_array($prefs)) {
70            foreach ($prefs as $name => $value) {
71                $this->preference[$name] = $value;
72            }
73            return $this;
74        } elseif (is_string($prefs) && isset($value)) {
75            $this->preference[$prefs] = $value;
76            return $this;
77        }
78        // get
79        return $this->preference;
80    }
81
82    /**
83     * Retrieve requested revision(s) and difftype from Ui\Revisions
84     *
85     * @return void
86     */
87    protected function preProcess()
88    {
89        global $INPUT;
90
91        // difflink icon click, eg. ?rev=123456789&do=diff
92        if ($INPUT->has('rev')) {
93            $this->old_rev = $INPUT->int('rev');
94            $this->new_rev = ''; // current revision
95        }
96
97        // submit button with two checked boxes
98        $rev2 = $INPUT->arr('rev2', []);
99        if (count($rev2) > 1) {
100            if ($rev2[0] == 'current') {
101                [$this->old_rev, $this->new_rev] = [$rev2[1], ''];
102            } elseif ($rev2[1] == 'current') {
103                [$this->old_rev, $this->new_rev] = [$rev2[0], ''];
104            } elseif ($rev2[0] < $rev2[1]) {
105                [$this->old_rev, $this->new_rev] = [$rev2[0], $rev2[1]];
106            } else {
107                [$this->old_rev, $this->new_rev] = [$rev2[1], $rev2[0]];
108            }
109        }
110
111        // diff view type
112        if ($INPUT->has('difftype')) {
113            // retrieve requested $difftype
114            $this->preference['difftype'] = $INPUT->str('difftype');
115        } else {
116            // read preference from DokuWiki cookie. PageDiff only
117            $this->preference['difftype'] = get_doku_pref('difftype', $mode);
118        }
119    }
120
121
122
123    /**
124     * Build header of diff HTML
125     *
126     * @param string $l_rev   Left revisions
127     * @param string $r_rev   Right revision
128     * @return string[] HTML snippets for diff header
129     */
130    public function buildDiffHead($l_rev, $r_rev)
131    {
132        global $lang;
133
134        // detect PageDiff or MediaDiff
135        switch (get_class($this->changelog)) {
136            case PageChangeLog::class :
137                $media_or_wikiFN = 'wikiFN';
138                $ml_or_wl = 'wl';
139                $media = false;
140                break;
141            case MediaChangeLog::class :
142                $media_or_wikiFN = 'mediaFN';
143                $ml_or_wl = 'ml';
144                $media = true;
145                break;
146        }
147
148        $head_separator = ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
149        $l_minor = $r_minor = '';
150
151        // left side
152        if (!$l_rev) {
153            $l_head = '&mdash;';
154        } else {
155            $l_info   = $this->changelog->getRevisionInfo($l_rev);
156            if ($l_info['user']) {
157                $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>';
158                if (auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>';
159            } else {
160                $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>';
161            }
162            $l_user  = '<span class="user">'.$l_user.'</span>';
163            $l_sum   = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : '';
164            if ($l_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"';
165
166            $l_head_title = ($media) ? dformat($l_rev) : $this->id.' ['.dformat($l_rev).']';
167            $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id,"rev=$l_rev").'">'
168                . $l_head_title.'</a></bdi>'.$head_separator.$l_user.' '.$l_sum;
169        }
170
171        // right side
172        if ($r_rev) {
173            $r_info   = $this->changelog->getRevisionInfo($r_rev);
174            if ($r_info['user']) {
175                $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>';
176                if (auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>';
177            } else {
178                $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>';
179            }
180            $r_user = '<span class="user">'.$r_user.'</span>';
181            $r_sum  = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : '';
182            if ($r_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
183
184            $r_head_title = ($media) ? dformat($r_rev) : $this->id.' ['.dformat($r_rev).']';
185            $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id,"rev=$r_rev").'">'
186                . $r_head_title.'</a></bdi>'.$head_separator.$r_user.' '.$r_sum;
187        } elseif ($_rev = @filemtime($media_or_wikiFN($this->id))) {
188            $_info   = $this->changelog->getRevisionInfo($_rev);
189            if ($_info['user']) {
190                $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>';
191                if (auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>';
192            } else {
193                $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>';
194            }
195            $_user = '<span class="user">'.$_user.'</span>';
196            $_sum  = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : '';
197            if ($_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"';
198
199            $r_head_title = ($media) ? dformat($_rev) : $this->id.' ['.dformat($_rev).']';
200            $r_head  = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id).'">'
201                . $r_head_title.'</a></bdi> '.'('.$lang['current'].')'.$head_separator.$_user.' '.$_sum;
202        }else{
203            $r_head = '&mdash; ('.$lang['current'].')';
204        }
205
206        return array($l_head, $r_head, $l_minor, $r_minor);
207    }
208
209}
210