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