xref: /dokuwiki/inc/Ui/PageRevisions.php (revision b370ebcdb8c1cf2da028da6a07616e3701bfbd40)
1*b370ebcdSSatoshi Sahara<?php
2*b370ebcdSSatoshi Sahara
3*b370ebcdSSatoshi Saharanamespace dokuwiki\Ui;
4*b370ebcdSSatoshi Sahara
5*b370ebcdSSatoshi Saharause dokuwiki\ChangeLog\PageChangeLog;
6*b370ebcdSSatoshi Saharause dokuwiki\Form\Form;
7*b370ebcdSSatoshi Sahara
8*b370ebcdSSatoshi Sahara/**
9*b370ebcdSSatoshi Sahara * DokuWiki PageRevisions Interface
10*b370ebcdSSatoshi Sahara *
11*b370ebcdSSatoshi Sahara * @package dokuwiki\Ui
12*b370ebcdSSatoshi Sahara */
13*b370ebcdSSatoshi Saharaclass PageRevisions extends Ui
14*b370ebcdSSatoshi Sahara{
15*b370ebcdSSatoshi Sahara    /* @var string */
16*b370ebcdSSatoshi Sahara    protected $id;
17*b370ebcdSSatoshi Sahara
18*b370ebcdSSatoshi Sahara    /**
19*b370ebcdSSatoshi Sahara     * PageRevisions Ui constructor
20*b370ebcdSSatoshi Sahara     *
21*b370ebcdSSatoshi Sahara     * @param string $id  id of page
22*b370ebcdSSatoshi Sahara     */
23*b370ebcdSSatoshi Sahara    public function __construct($id)
24*b370ebcdSSatoshi Sahara    {
25*b370ebcdSSatoshi Sahara        global $ID, $INFO;
26*b370ebcdSSatoshi Sahara        if (!$id) $id = $INFO['id'];
27*b370ebcdSSatoshi Sahara        $this->id = $id;
28*b370ebcdSSatoshi Sahara    }
29*b370ebcdSSatoshi Sahara
30*b370ebcdSSatoshi Sahara    /**
31*b370ebcdSSatoshi Sahara     * Display list of old revisions of the page
32*b370ebcdSSatoshi Sahara     *
33*b370ebcdSSatoshi Sahara     * @author Andreas Gohr <andi@splitbrain.org>
34*b370ebcdSSatoshi Sahara     * @author Ben Coburn <btcoburn@silicodon.net>
35*b370ebcdSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
36*b370ebcdSSatoshi Sahara     * @author Satoshi Sahara <sahara.satoshi@gmail.com>
37*b370ebcdSSatoshi Sahara     *
38*b370ebcdSSatoshi Sahara     * @param int $first  skip the first n changelog lines
39*b370ebcdSSatoshi Sahara     * @return void
40*b370ebcdSSatoshi Sahara     */
41*b370ebcdSSatoshi Sahara    public function show($first = 0)
42*b370ebcdSSatoshi Sahara    {
43*b370ebcdSSatoshi Sahara        global $lang;
44*b370ebcdSSatoshi Sahara
45*b370ebcdSSatoshi Sahara        // get revisions, and set correct pagenation parameters (first, hasNext)
46*b370ebcdSSatoshi Sahara        if ($first === null) $first = 0;
47*b370ebcdSSatoshi Sahara        $hasNext = false;
48*b370ebcdSSatoshi Sahara        $revisions = $this->getRevisions($first, $hasNext);
49*b370ebcdSSatoshi Sahara
50*b370ebcdSSatoshi Sahara        // print intro
51*b370ebcdSSatoshi Sahara        print p_locale_xhtml('revisions');
52*b370ebcdSSatoshi Sahara
53*b370ebcdSSatoshi Sahara        // create the form
54*b370ebcdSSatoshi Sahara        $form = new Form([
55*b370ebcdSSatoshi Sahara                'id' => 'page__revisions',
56*b370ebcdSSatoshi Sahara                'class' => 'changes',
57*b370ebcdSSatoshi Sahara        ]);
58*b370ebcdSSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
59*b370ebcdSSatoshi Sahara
60*b370ebcdSSatoshi Sahara        // start listing
61*b370ebcdSSatoshi Sahara        $form->addTagOpen('ul');
62*b370ebcdSSatoshi Sahara        foreach ($revisions as $info) {
63*b370ebcdSSatoshi Sahara            $rev = $info['date'];
64*b370ebcdSSatoshi Sahara            $class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
65*b370ebcdSSatoshi Sahara            $form->addTagOpen('li')->addClass($class);
66*b370ebcdSSatoshi Sahara            $form->addTagOpen('div')->addClass('li');
67*b370ebcdSSatoshi Sahara
68*b370ebcdSSatoshi Sahara            if (page_exists($this->id, $rev)) {
69*b370ebcdSSatoshi Sahara                $form->addCheckbox('rev2[]')->val($rev);
70*b370ebcdSSatoshi Sahara            } else {
71*b370ebcdSSatoshi Sahara                $form->addCheckbox('')->val($rev)->attr('disabled','disabled');
72*b370ebcdSSatoshi Sahara            }
73*b370ebcdSSatoshi Sahara            $form->addHTML(' ');
74*b370ebcdSSatoshi Sahara
75*b370ebcdSSatoshi Sahara            $objRevInfo = $this->getObjRevInfo($info);
76*b370ebcdSSatoshi Sahara            $html = implode(' ', [
77*b370ebcdSSatoshi Sahara                $objRevInfo->editDate(),          // edit date and time
78*b370ebcdSSatoshi Sahara                $objRevInfo->difflink(),          // link to diffview icon
79*b370ebcdSSatoshi Sahara                $objRevInfo->itemName(),          // name of page or media
80*b370ebcdSSatoshi Sahara                $objRevInfo->editSummary(),       // edit summary
81*b370ebcdSSatoshi Sahara                $objRevInfo->editor(),            // editor info
82*b370ebcdSSatoshi Sahara                $objRevInfo->sizechange(),        // size change indicator
83*b370ebcdSSatoshi Sahara                $objRevInfo->currentIndicator(),  // current indicator (only when k=1)
84*b370ebcdSSatoshi Sahara            ]);
85*b370ebcdSSatoshi Sahara            $form->addHTML($html);
86*b370ebcdSSatoshi Sahara            $form->addTagClose('div');
87*b370ebcdSSatoshi Sahara            $form->addTagClose('li');
88*b370ebcdSSatoshi Sahara        }
89*b370ebcdSSatoshi Sahara        $form->addTagClose('ul');  // end of revision list
90*b370ebcdSSatoshi Sahara
91*b370ebcdSSatoshi Sahara        // show button for diff view
92*b370ebcdSSatoshi Sahara        $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
93*b370ebcdSSatoshi Sahara
94*b370ebcdSSatoshi Sahara        $form->addTagClose('div'); // close div class=no
95*b370ebcdSSatoshi Sahara
96*b370ebcdSSatoshi Sahara        print $form->toHTML('Revisions');
97*b370ebcdSSatoshi Sahara
98*b370ebcdSSatoshi Sahara        // provide navigation for pagenated revision list (of pages and/or media files)
99*b370ebcdSSatoshi Sahara        print $this->htmlNavigation($first, $hasNext);
100*b370ebcdSSatoshi Sahara    }
101*b370ebcdSSatoshi Sahara
102*b370ebcdSSatoshi Sahara    /**
103*b370ebcdSSatoshi Sahara     * Get revisions, and set correct pagenation parameters (first, hasNext)
104*b370ebcdSSatoshi Sahara     *
105*b370ebcdSSatoshi Sahara     * @param int  $first
106*b370ebcdSSatoshi Sahara     * @param bool $hasNext
107*b370ebcdSSatoshi Sahara     * @return array  revisions to be shown in a pagenated list
108*b370ebcdSSatoshi Sahara     * @see also https://www.dokuwiki.org/devel:changelog
109*b370ebcdSSatoshi Sahara     */
110*b370ebcdSSatoshi Sahara    protected function getRevisions(&$first, &$hasNext)
111*b370ebcdSSatoshi Sahara    {
112*b370ebcdSSatoshi Sahara        global $INFO, $conf;
113*b370ebcdSSatoshi Sahara
114*b370ebcdSSatoshi Sahara        $changelog = new PageChangeLog($INFO['id']);
115*b370ebcdSSatoshi Sahara
116*b370ebcdSSatoshi Sahara        $revisions = [];
117*b370ebcdSSatoshi Sahara
118*b370ebcdSSatoshi Sahara        /* we need to get one additional log entry to be able to
119*b370ebcdSSatoshi Sahara         * decide if this is the last page or is there another one.
120*b370ebcdSSatoshi Sahara         * see also Ui\Recent::getRecents()
121*b370ebcdSSatoshi Sahara         */
122*b370ebcdSSatoshi Sahara        $revlist = $changelog->getRevisions($first, $conf['recent'] +1);
123*b370ebcdSSatoshi Sahara        if (count($revlist) == 0 && $first != 0) {
124*b370ebcdSSatoshi Sahara            $first = 0;
125*b370ebcdSSatoshi Sahara            $revlist = $changelog->getRevisions($first, $conf['recent'] +1);
126*b370ebcdSSatoshi Sahara        }
127*b370ebcdSSatoshi Sahara        $exists = $INFO['exists'];
128*b370ebcdSSatoshi Sahara        if ($first === 0 && $exists) {
129*b370ebcdSSatoshi Sahara            // add current page as revision[0]
130*b370ebcdSSatoshi Sahara            $revisions[] = array(
131*b370ebcdSSatoshi Sahara                    'date' => $INFO['lastmod'],
132*b370ebcdSSatoshi Sahara                    'ip'   => null,
133*b370ebcdSSatoshi Sahara                    'type' => $INFO['meta']['last_change']['type'],
134*b370ebcdSSatoshi Sahara                    'id'   => $INFO['id'],
135*b370ebcdSSatoshi Sahara                    'user' => $INFO['editor'],
136*b370ebcdSSatoshi Sahara                    'sum'  => $INFO['sum'],
137*b370ebcdSSatoshi Sahara                    'extra' => null,
138*b370ebcdSSatoshi Sahara                    'sizechange' => $INFO['meta']['last_change']['sizechange'],
139*b370ebcdSSatoshi Sahara                    'current' => true,
140*b370ebcdSSatoshi Sahara            );
141*b370ebcdSSatoshi Sahara        }
142*b370ebcdSSatoshi Sahara
143*b370ebcdSSatoshi Sahara        // decide if this is the last page or is there another one
144*b370ebcdSSatoshi Sahara        $hasNext = false;
145*b370ebcdSSatoshi Sahara        if (count($revlist) > $conf['recent']) {
146*b370ebcdSSatoshi Sahara            $hasNext = true;
147*b370ebcdSSatoshi Sahara            array_pop($revlist); // remove one additional log entry
148*b370ebcdSSatoshi Sahara        }
149*b370ebcdSSatoshi Sahara
150*b370ebcdSSatoshi Sahara        // append each revison info array to the revisions
151*b370ebcdSSatoshi Sahara        foreach ($revlist as $rev) {
152*b370ebcdSSatoshi Sahara            $revisions[] = $changelog->getRevisionInfo($rev);
153*b370ebcdSSatoshi Sahara        }
154*b370ebcdSSatoshi Sahara        return $revisions;
155*b370ebcdSSatoshi Sahara    }
156*b370ebcdSSatoshi Sahara
157*b370ebcdSSatoshi Sahara    /**
158*b370ebcdSSatoshi Sahara     * Navigation buttons for Pagenation (prev/next)
159*b370ebcdSSatoshi Sahara     *
160*b370ebcdSSatoshi Sahara     * @param int  $first
161*b370ebcdSSatoshi Sahara     * @param bool $hasNext
162*b370ebcdSSatoshi Sahara     * @return array  html
163*b370ebcdSSatoshi Sahara     */
164*b370ebcdSSatoshi Sahara    protected function htmlNavigation($first, $hasNext)
165*b370ebcdSSatoshi Sahara    {
166*b370ebcdSSatoshi Sahara        global $conf;
167*b370ebcdSSatoshi Sahara
168*b370ebcdSSatoshi Sahara        $html = '<div class="pagenav">';
169*b370ebcdSSatoshi Sahara        $last = $first + $conf['recent'];
170*b370ebcdSSatoshi Sahara        if ($first > 0) {
171*b370ebcdSSatoshi Sahara            $first = max($first - $conf['recent'], 0);
172*b370ebcdSSatoshi Sahara            $html.= '<div class="pagenav-prev">';
173*b370ebcdSSatoshi Sahara            $html.= html_btn('newer', $this->id, "p" ,['do' => 'revisions', 'first' => $first]);
174*b370ebcdSSatoshi Sahara            $html.= '</div>';
175*b370ebcdSSatoshi Sahara        }
176*b370ebcdSSatoshi Sahara        if ($hasNext) {
177*b370ebcdSSatoshi Sahara            $html.= '<div class="pagenav-next">';
178*b370ebcdSSatoshi Sahara            $html.= html_btn('older', $this->id, "n", ['do' => 'revisions', 'first' => $last]);
179*b370ebcdSSatoshi Sahara            $html.= '</div>';
180*b370ebcdSSatoshi Sahara        }
181*b370ebcdSSatoshi Sahara        $html.= '</div>';
182*b370ebcdSSatoshi Sahara        return $html;
183*b370ebcdSSatoshi Sahara    }
184*b370ebcdSSatoshi Sahara
185*b370ebcdSSatoshi Sahara    /**
186*b370ebcdSSatoshi Sahara     * Returns instance of objRevInfo
187*b370ebcdSSatoshi Sahara     *
188*b370ebcdSSatoshi Sahara     * @param array $info  Revision info structure of a page or media file
189*b370ebcdSSatoshi Sahara     * @return objRevInfo object (anonymous class)
190*b370ebcdSSatoshi Sahara     */
191*b370ebcdSSatoshi Sahara    protected function getObjRevInfo(array $info)
192*b370ebcdSSatoshi Sahara    {
193*b370ebcdSSatoshi Sahara        return new class ($info) // anonymous class (objRevInfo)
194*b370ebcdSSatoshi Sahara        {
195*b370ebcdSSatoshi Sahara            protected $info;
196*b370ebcdSSatoshi Sahara
197*b370ebcdSSatoshi Sahara            public function __construct(array $info)
198*b370ebcdSSatoshi Sahara            {
199*b370ebcdSSatoshi Sahara                $this->info = $info;
200*b370ebcdSSatoshi Sahara            }
201*b370ebcdSSatoshi Sahara
202*b370ebcdSSatoshi Sahara            // current indicator
203*b370ebcdSSatoshi Sahara            public function currentIndicator()
204*b370ebcdSSatoshi Sahara            {
205*b370ebcdSSatoshi Sahara                global $lang;
206*b370ebcdSSatoshi Sahara                return ($this->info['current']) ? '('.$lang['current'].')' : '';
207*b370ebcdSSatoshi Sahara            }
208*b370ebcdSSatoshi Sahara
209*b370ebcdSSatoshi Sahara            // edit date and time of the page or media file
210*b370ebcdSSatoshi Sahara            public function editDate()
211*b370ebcdSSatoshi Sahara            {
212*b370ebcdSSatoshi Sahara                return '<span class="date">'. dformat($this->info['date']) .'</span>';
213*b370ebcdSSatoshi Sahara            }
214*b370ebcdSSatoshi Sahara
215*b370ebcdSSatoshi Sahara            // edit summary
216*b370ebcdSSatoshi Sahara            public function editSummary()
217*b370ebcdSSatoshi Sahara            {
218*b370ebcdSSatoshi Sahara                return '<span class="sum">'.' – '. hsc($this->info['sum']).'</span>';
219*b370ebcdSSatoshi Sahara            }
220*b370ebcdSSatoshi Sahara
221*b370ebcdSSatoshi Sahara            // editor of the page or media file
222*b370ebcdSSatoshi Sahara            public function editor()
223*b370ebcdSSatoshi Sahara            {
224*b370ebcdSSatoshi Sahara                // slightly different with display of Ui\Recent, i.e. external edit
225*b370ebcdSSatoshi Sahara                global $lang;
226*b370ebcdSSatoshi Sahara                $html = '<span class="user">';
227*b370ebcdSSatoshi Sahara                if (!$this->info['user'] && !$this->info['ip']) {
228*b370ebcdSSatoshi Sahara                    $html.= '('.$lang['external_edit'].')';
229*b370ebcdSSatoshi Sahara                } elseif ($this->info['user']) {
230*b370ebcdSSatoshi Sahara                    $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
231*b370ebcdSSatoshi Sahara                    if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
232*b370ebcdSSatoshi Sahara                } else {
233*b370ebcdSSatoshi Sahara                    $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
234*b370ebcdSSatoshi Sahara                }
235*b370ebcdSSatoshi Sahara                $html.= '</span>';
236*b370ebcdSSatoshi Sahara                return $html;
237*b370ebcdSSatoshi Sahara            }
238*b370ebcdSSatoshi Sahara
239*b370ebcdSSatoshi Sahara            // name of the page or media file
240*b370ebcdSSatoshi Sahara            public function itemName()
241*b370ebcdSSatoshi Sahara            {
242*b370ebcdSSatoshi Sahara                // slightly different with display of Ui\Recent, i.e. revison may not exists
243*b370ebcdSSatoshi Sahara                $id = $this->info['id'];
244*b370ebcdSSatoshi Sahara                $rev = $this->info['date'];
245*b370ebcdSSatoshi Sahara
246*b370ebcdSSatoshi Sahara                if (isset($this->info['media'])) {
247*b370ebcdSSatoshi Sahara                    // media file revision
248*b370ebcdSSatoshi Sahara                    if (isset($this->info['current'])) {
249*b370ebcdSSatoshi Sahara                        $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view'], '&');
250*b370ebcdSSatoshi Sahara                        $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
251*b370ebcdSSatoshi Sahara                    } elseif (file_exists(mediaFN($id, $rev))) {
252*b370ebcdSSatoshi Sahara                        $href = media_managerURL(['image'=> $id, 'tab_details'=> 'view', 'rev'=> $rev], '&');
253*b370ebcdSSatoshi Sahara                        $html = '<a href="'.$href.'" class="wikilink1">'.$id.'</a>';
254*b370ebcdSSatoshi Sahara                    } else {
255*b370ebcdSSatoshi Sahara                        $html = $id;
256*b370ebcdSSatoshi Sahara                    }
257*b370ebcdSSatoshi Sahara                    return $html;
258*b370ebcdSSatoshi Sahara                } else {
259*b370ebcdSSatoshi Sahara                    // page revision
260*b370ebcdSSatoshi Sahara                    $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
261*b370ebcdSSatoshi Sahara                    if (!$display_name) $display_name = $id;
262*b370ebcdSSatoshi Sahara                    if ($this->info['current'] || page_exists($id, $rev)) {
263*b370ebcdSSatoshi Sahara                        $href = wl($id, "rev=$rev", false, '&');
264*b370ebcdSSatoshi Sahara                        $html = '<a href="'.$href.'" class="wikilink1">'.$display_name.'</a>';
265*b370ebcdSSatoshi Sahara                    } else {
266*b370ebcdSSatoshi Sahara                        $html = $display_name;
267*b370ebcdSSatoshi Sahara                    }
268*b370ebcdSSatoshi Sahara                    return $html;
269*b370ebcdSSatoshi Sahara                }
270*b370ebcdSSatoshi Sahara            }
271*b370ebcdSSatoshi Sahara
272*b370ebcdSSatoshi Sahara            // icon difflink
273*b370ebcdSSatoshi Sahara            public function difflink()
274*b370ebcdSSatoshi Sahara            {
275*b370ebcdSSatoshi Sahara                global $lang;
276*b370ebcdSSatoshi Sahara                $id = $this->info['id'];
277*b370ebcdSSatoshi Sahara                $rev = $this->info['date'];
278*b370ebcdSSatoshi Sahara
279*b370ebcdSSatoshi Sahara                if (isset($this->info['media'])) {
280*b370ebcdSSatoshi Sahara                    // media file revision
281*b370ebcdSSatoshi Sahara                    if (isset($this->info['current']) || !file_exists(mediaFN($id, $rev))) {
282*b370ebcdSSatoshi Sahara                        $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
283*b370ebcdSSatoshi Sahara                    } else {
284*b370ebcdSSatoshi Sahara                        $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
285*b370ebcdSSatoshi Sahara                        $html = '<a href="'.$href.'" class="diff_link">'
286*b370ebcdSSatoshi Sahara                              . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
287*b370ebcdSSatoshi Sahara                              . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
288*b370ebcdSSatoshi Sahara                              . '</a> ';
289*b370ebcdSSatoshi Sahara                    }
290*b370ebcdSSatoshi Sahara                    return $html;
291*b370ebcdSSatoshi Sahara                } else {
292*b370ebcdSSatoshi Sahara                    // page revision
293*b370ebcdSSatoshi Sahara                    if ($this->info['current'] || !page_exists($id, $rev)) {
294*b370ebcdSSatoshi Sahara                        $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
295*b370ebcdSSatoshi Sahara                    } else {
296*b370ebcdSSatoshi Sahara                        $href = wl($id, "rev=$rev,do=diff", false, '&');
297*b370ebcdSSatoshi Sahara                        $html = '<a href="'.$href.'" class="diff_link">'
298*b370ebcdSSatoshi Sahara                              . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
299*b370ebcdSSatoshi Sahara                              . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
300*b370ebcdSSatoshi Sahara                              . '</a>';
301*b370ebcdSSatoshi Sahara                    }
302*b370ebcdSSatoshi Sahara                    return $html;
303*b370ebcdSSatoshi Sahara                }
304*b370ebcdSSatoshi Sahara            }
305*b370ebcdSSatoshi Sahara
306*b370ebcdSSatoshi Sahara            // size change
307*b370ebcdSSatoshi Sahara            public function sizeChange()
308*b370ebcdSSatoshi Sahara            {
309*b370ebcdSSatoshi Sahara                $class = 'sizechange';
310*b370ebcdSSatoshi Sahara                $value = filesize_h(abs($this->info['sizechange']));
311*b370ebcdSSatoshi Sahara                if ($this->info['sizechange'] > 0) {
312*b370ebcdSSatoshi Sahara                    $class .= ' positive';
313*b370ebcdSSatoshi Sahara                    $value = '+' . $value;
314*b370ebcdSSatoshi Sahara                } elseif ($this->info['sizechange'] < 0) {
315*b370ebcdSSatoshi Sahara                    $class .= ' negative';
316*b370ebcdSSatoshi Sahara                    $value = '-' . $value;
317*b370ebcdSSatoshi Sahara                } else {
318*b370ebcdSSatoshi Sahara                    $value = '±' . $value;
319*b370ebcdSSatoshi Sahara                }
320*b370ebcdSSatoshi Sahara                return '<span class="'.$class.'">'.$value.'</span>';
321*b370ebcdSSatoshi Sahara            }
322*b370ebcdSSatoshi Sahara        }; // end of anonymous class (objRevInfo)
323*b370ebcdSSatoshi Sahara    }
324*b370ebcdSSatoshi Sahara
325*b370ebcdSSatoshi Sahara}
326