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