xref: /dokuwiki/inc/Ui/Recent.php (revision 21b96b634a5fac73dfd05d00b10fedc81155f46e)
13d7df1dcSSatoshi Sahara<?php
23d7df1dcSSatoshi Sahara
33d7df1dcSSatoshi Saharanamespace dokuwiki\Ui;
43d7df1dcSSatoshi Sahara
53d7df1dcSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog;
63d7df1dcSSatoshi Saharause dokuwiki\Extension\Event;
73d7df1dcSSatoshi Saharause dokuwiki\Form\Form;
83d7df1dcSSatoshi Sahara
93d7df1dcSSatoshi Sahara/**
109e316641SSatoshi Sahara * DokuWiki Recent Interface
113d7df1dcSSatoshi Sahara *
123d7df1dcSSatoshi Sahara * @package dokuwiki\Ui
133d7df1dcSSatoshi Sahara */
143d7df1dcSSatoshi Saharaclass Recent extends Ui
153d7df1dcSSatoshi Sahara{
169e316641SSatoshi Sahara    protected $first;
179e316641SSatoshi Sahara    protected $show_changes;
189e316641SSatoshi Sahara
199e316641SSatoshi Sahara    /**
209e316641SSatoshi Sahara     * Recent Ui constructor
219e316641SSatoshi Sahara     *
229e316641SSatoshi Sahara     * @param int $first  skip the first n changelog lines
239e316641SSatoshi Sahara     * @param string $show_changes  type of changes to show; pages, mediafiles, or both
249e316641SSatoshi Sahara     */
259e316641SSatoshi Sahara    public function __construct($first = 0, $show_changes = 'both')
269e316641SSatoshi Sahara    {
279e316641SSatoshi Sahara        $this->first        = $first;
289e316641SSatoshi Sahara        $this->show_changes = $show_changes;
299e316641SSatoshi Sahara    }
309e316641SSatoshi Sahara
313d7df1dcSSatoshi Sahara    /**
323d7df1dcSSatoshi Sahara     * Display recent changes
333d7df1dcSSatoshi Sahara     *
343d7df1dcSSatoshi Sahara     * @author Andreas Gohr <andi@splitbrain.org>
353d7df1dcSSatoshi Sahara     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
363d7df1dcSSatoshi Sahara     * @author Ben Coburn <btcoburn@silicodon.net>
373d7df1dcSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
38*21b96b63SSatoshi Sahara     * @author Satoshi Sahara <sahara.satoshi@gmail.com>
393d7df1dcSSatoshi Sahara     *
403d7df1dcSSatoshi Sahara     * @triggers HTML_RECENTFORM_OUTPUT
413d7df1dcSSatoshi Sahara     * @return void
423d7df1dcSSatoshi Sahara     */
439e316641SSatoshi Sahara    public function show()
443d7df1dcSSatoshi Sahara    {
453d7df1dcSSatoshi Sahara        global $lang;
463d7df1dcSSatoshi Sahara        global $ID;
473d7df1dcSSatoshi Sahara
48*21b96b63SSatoshi Sahara        // get recent items, and set correct pagenation parameters (first, hasNext)
499e316641SSatoshi Sahara        $first = $this->first;
50*21b96b63SSatoshi Sahara        $hasNext = null;
51*21b96b63SSatoshi Sahara        $recents = $this->getRecents($first, $hasNext);
523d7df1dcSSatoshi Sahara
533d7df1dcSSatoshi Sahara        // print intro
543d7df1dcSSatoshi Sahara        print p_locale_xhtml('recent');
553d7df1dcSSatoshi Sahara
563d7df1dcSSatoshi Sahara        if (getNS($ID) != '') {
573d7df1dcSSatoshi Sahara            print '<div class="level1"><p>'
583d7df1dcSSatoshi Sahara                . sprintf($lang['recent_global'], getNS($ID), wl('', 'do=recent'))
593d7df1dcSSatoshi Sahara                .'</p></div>';
603d7df1dcSSatoshi Sahara        }
613d7df1dcSSatoshi Sahara
623d7df1dcSSatoshi Sahara        // create the form
63*21b96b63SSatoshi Sahara        $form = new Form(['id'=>'dw__recent', 'method'=>'GET', 'action'=> wl($ID), 'class'=>'changes']);
643d7df1dcSSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
653d7df1dcSSatoshi Sahara        $form->setHiddenField('sectok', null);
663d7df1dcSSatoshi Sahara        $form->setHiddenField('do', 'recent');
673d7df1dcSSatoshi Sahara        $form->setHiddenField('id', $ID);
683d7df1dcSSatoshi Sahara
693d7df1dcSSatoshi Sahara        // show dropdown selector, whether include not only recent pages but also recent media files?
703d7df1dcSSatoshi Sahara        if ($conf['mediarevisions']) {
71*21b96b63SSatoshi Sahara            $this->addRecentItemSelector($form);
72*21b96b63SSatoshi Sahara        }
73*21b96b63SSatoshi Sahara
74*21b96b63SSatoshi Sahara        // start listing of recent items
75*21b96b63SSatoshi Sahara        $form->addTagOpen('ul');
76*21b96b63SSatoshi Sahara        foreach ($recents as $recent) {
77*21b96b63SSatoshi Sahara            $objRevInfo = $this->getObjRevInfo($recent);
78*21b96b63SSatoshi Sahara            $class = ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor': '';
79*21b96b63SSatoshi Sahara            $form->addTagOpen('li')->addClass($class);
80*21b96b63SSatoshi Sahara            $form->addTagOpen('div')->addClass('li');
81*21b96b63SSatoshi Sahara            $html = implode(' ', [
82*21b96b63SSatoshi Sahara                $objRevInfo->itemIcon(),          // filetype icon
83*21b96b63SSatoshi Sahara                $objRevInfo->editDate(),          // edit date and time
84*21b96b63SSatoshi Sahara                $objRevInfo->difflink(),          // link to diffview icon
85*21b96b63SSatoshi Sahara                $objRevInfo->revisionlink(),      // linkto revisions icon
86*21b96b63SSatoshi Sahara                $objRevInfo->itemName(),          // name of page or media
87*21b96b63SSatoshi Sahara                $objRevInfo->editSummary(),       // edit summary
88*21b96b63SSatoshi Sahara                $objRevInfo->editor(),            // editor info
89*21b96b63SSatoshi Sahara                html_sizechange($recent['sizechange']), // size change indicator
90*21b96b63SSatoshi Sahara            ]);
91*21b96b63SSatoshi Sahara            $form->addHTML($html);
92*21b96b63SSatoshi Sahara            $form->addTagClose('div');
93*21b96b63SSatoshi Sahara            $form->addTagClose('li');
94*21b96b63SSatoshi Sahara        }
95*21b96b63SSatoshi Sahara        $form->addTagClose('ul');
96*21b96b63SSatoshi Sahara
97*21b96b63SSatoshi Sahara        $form->addTagClose('div'); // close div class=no
98*21b96b63SSatoshi Sahara
99*21b96b63SSatoshi Sahara        // provide navigation for pagenated recent list (of pages and/or media files)
100*21b96b63SSatoshi Sahara        $form->addHTML($this->htmlNavigation($first, $hasNext));
101*21b96b63SSatoshi Sahara
102*21b96b63SSatoshi Sahara        // emit HTML_CRECENTFORM_OUTPUT event
103*21b96b63SSatoshi Sahara        Event::createAndTrigger('HTML_RECENTFORM_OUTPUT', $form, null, false);
104*21b96b63SSatoshi Sahara        print $form->toHTML();
105*21b96b63SSatoshi Sahara    }
106*21b96b63SSatoshi Sahara
107*21b96b63SSatoshi Sahara    /**
108*21b96b63SSatoshi Sahara     * Get recent items, and set correct pagenation parameters (first, hasNext)
109*21b96b63SSatoshi Sahara     *
110*21b96b63SSatoshi Sahara     * @param int  $first
111*21b96b63SSatoshi Sahara     * @param bool $hasNext
112*21b96b63SSatoshi Sahara     * @return array  recent items to be shown in a pagenated list
113*21b96b63SSatoshi Sahara     *
114*21b96b63SSatoshi Sahara     * @see also dokuwiki\Changelog::getRevisionInfo()
115*21b96b63SSatoshi Sahara     */
116*21b96b63SSatoshi Sahara    protected function getRecents(&$first, &$hasNext)
117*21b96b63SSatoshi Sahara    {
118*21b96b63SSatoshi Sahara        global $ID, $conf;
119*21b96b63SSatoshi Sahara
120*21b96b63SSatoshi Sahara        $flags = 0;
121*21b96b63SSatoshi Sahara        if ($this->show_changes == 'mediafiles' && $conf['mediarevisions']) {
122*21b96b63SSatoshi Sahara            $flags = RECENTS_MEDIA_CHANGES;
123*21b96b63SSatoshi Sahara        } elseif ($this->show_changes == 'pages') {
124*21b96b63SSatoshi Sahara            $flags = 0;
125*21b96b63SSatoshi Sahara        } elseif ($conf['mediarevisions']) {
126*21b96b63SSatoshi Sahara            $flags = RECENTS_MEDIA_PAGES_MIXED;
127*21b96b63SSatoshi Sahara        }
128*21b96b63SSatoshi Sahara
129*21b96b63SSatoshi Sahara        /* we need to get one additionally log entry to be able to
130*21b96b63SSatoshi Sahara         * decide if this is the last page or is there another one.
131*21b96b63SSatoshi Sahara         * This is the cheapest solution to get this information.
132*21b96b63SSatoshi Sahara         */
133*21b96b63SSatoshi Sahara        $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
134*21b96b63SSatoshi Sahara        if (count($recents) == 0 && $first != 0) {
135*21b96b63SSatoshi Sahara            $first = 0;
136*21b96b63SSatoshi Sahara            $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
137*21b96b63SSatoshi Sahara        }
138*21b96b63SSatoshi Sahara
139*21b96b63SSatoshi Sahara        $hasNext = false;
140*21b96b63SSatoshi Sahara        if (count($recents) > $conf['recent']) {
141*21b96b63SSatoshi Sahara            $hasNext = true;
142*21b96b63SSatoshi Sahara            array_pop($recents); // remove extra log entry
143*21b96b63SSatoshi Sahara        }
144*21b96b63SSatoshi Sahara        return $recents;
145*21b96b63SSatoshi Sahara    }
146*21b96b63SSatoshi Sahara
147*21b96b63SSatoshi Sahara    /**
148*21b96b63SSatoshi Sahara     * Navigation buttons for Pagenation (prev/next)
149*21b96b63SSatoshi Sahara     *
150*21b96b63SSatoshi Sahara     * @param int  $first
151*21b96b63SSatoshi Sahara     * @param bool $hasNext
152*21b96b63SSatoshi Sahara     * @return array  html
153*21b96b63SSatoshi Sahara     */
154*21b96b63SSatoshi Sahara    protected function htmlNavigation($first, $hasNext)
155*21b96b63SSatoshi Sahara    {
156*21b96b63SSatoshi Sahara        global $conf, $lang;
157*21b96b63SSatoshi Sahara
158*21b96b63SSatoshi Sahara        $last = $first + $conf['recent'];
159*21b96b63SSatoshi Sahara        $html = '<div class="pagenav">';
160*21b96b63SSatoshi Sahara        if ($first > 0) {
161*21b96b63SSatoshi Sahara            $first = max($first - $conf['recent'], 0);
162*21b96b63SSatoshi Sahara            $html.= '<div class="pagenav-prev">';
163*21b96b63SSatoshi Sahara            $html.= '<button type="submit" name="first['.$first.']" accesskey="n"'
164*21b96b63SSatoshi Sahara                  . ' title="'.$lang['btn_newer'].' [N]" class="button show">'
165*21b96b63SSatoshi Sahara                  . $lang['btn_newer']
166*21b96b63SSatoshi Sahara                  . '</button>';
167*21b96b63SSatoshi Sahara            $html.= '</div>';
168*21b96b63SSatoshi Sahara        }
169*21b96b63SSatoshi Sahara        if ($hasNext) {
170*21b96b63SSatoshi Sahara            $html.= '<div class="pagenav-next">';
171*21b96b63SSatoshi Sahara            $html.= '<button type="submit" name="first['.$last.']" accesskey="p"'
172*21b96b63SSatoshi Sahara                  . ' title="'.$lang['btn_older'].' [P]" class="button show">'
173*21b96b63SSatoshi Sahara                  . $lang['btn_older']
174*21b96b63SSatoshi Sahara                  . '</button>';
175*21b96b63SSatoshi Sahara            $html.= '</div>';
176*21b96b63SSatoshi Sahara        }
177*21b96b63SSatoshi Sahara        $html.= '</div>';
178*21b96b63SSatoshi Sahara        return $html;
179*21b96b63SSatoshi Sahara    }
180*21b96b63SSatoshi Sahara
181*21b96b63SSatoshi Sahara    /**
182*21b96b63SSatoshi Sahara     * Add dropdown selector of item types to the form instance
183*21b96b63SSatoshi Sahara     *
184*21b96b63SSatoshi Sahara     * @param Form $form
185*21b96b63SSatoshi Sahara     * @return void
186*21b96b63SSatoshi Sahara     */
187*21b96b63SSatoshi Sahara    protected function addRecentItemSelector(Form $form)
188*21b96b63SSatoshi Sahara    {
189*21b96b63SSatoshi Sahara        global $lang;
190*21b96b63SSatoshi Sahara
1913d7df1dcSSatoshi Sahara        $form->addTagOpen('div')->addClass('changeType');
1923d7df1dcSSatoshi Sahara        $options = array(
1933d7df1dcSSatoshi Sahara                    'pages'      => $lang['pages_changes'],
1943d7df1dcSSatoshi Sahara                    'mediafiles' => $lang['media_changes'],
1953d7df1dcSSatoshi Sahara                    'both'       => $lang['both_changes'],
1963d7df1dcSSatoshi Sahara        );
1973d7df1dcSSatoshi Sahara        $form->addDropdown('show_changes', $options, $lang['changes_type'])
198*21b96b63SSatoshi Sahara                ->val($this->show_changes)->addClass('quickselect');
1993d7df1dcSSatoshi Sahara        $form->addButton('do[recent]', $lang['btn_apply'])->attr('type','submit');
2003d7df1dcSSatoshi Sahara        $form->addTagClose('div');
2013d7df1dcSSatoshi Sahara    }
2023d7df1dcSSatoshi Sahara
203*21b96b63SSatoshi Sahara    /**
204*21b96b63SSatoshi Sahara     * Returns instance of objRevInfo
205*21b96b63SSatoshi Sahara     * @param array $info  Revision info structure of page or media
206*21b96b63SSatoshi Sahara     * @return (anonymous class) object
207*21b96b63SSatoshi Sahara     */
208*21b96b63SSatoshi Sahara    protected function getObjRevInfo(array $info)
209*21b96b63SSatoshi Sahara    {
210*21b96b63SSatoshi Sahara        return new class ($info) // anonymous class
211*21b96b63SSatoshi Sahara        {
212*21b96b63SSatoshi Sahara            protected $info;
2133d7df1dcSSatoshi Sahara
214*21b96b63SSatoshi Sahara            public function __construct(array $info)
215*21b96b63SSatoshi Sahara            {
216*21b96b63SSatoshi Sahara                $this->info = $info;
2173d7df1dcSSatoshi Sahara            }
2183d7df1dcSSatoshi Sahara
219*21b96b63SSatoshi Sahara            // fileicon of the page or media file
220*21b96b63SSatoshi Sahara            public function itemIcon()
221*21b96b63SSatoshi Sahara            {
222*21b96b63SSatoshi Sahara                $id = $this->info['id'];
223*21b96b63SSatoshi Sahara                if (isset($this->info['media'])) {
224*21b96b63SSatoshi Sahara                    $html = media_printicon($id);
225*21b96b63SSatoshi Sahara                } else {
226*21b96b63SSatoshi Sahara                    $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
227*21b96b63SSatoshi Sahara                }
228*21b96b63SSatoshi Sahara                return $html;
229*21b96b63SSatoshi Sahara            }
2303d7df1dcSSatoshi Sahara
231*21b96b63SSatoshi Sahara            // edit date and time of the page or media file
232*21b96b63SSatoshi Sahara            public function editDate()
233*21b96b63SSatoshi Sahara            {
234*21b96b63SSatoshi Sahara                $date = $this->info['date'];
235*21b96b63SSatoshi Sahara                $html = '<span class="date">'. dformat($date) .'</span>';
236*21b96b63SSatoshi Sahara                return $html;
237*21b96b63SSatoshi Sahara            }
238*21b96b63SSatoshi Sahara
239*21b96b63SSatoshi Sahara            // icon difflink
240*21b96b63SSatoshi Sahara            public function difflink()
241*21b96b63SSatoshi Sahara            {
242*21b96b63SSatoshi Sahara                global $lang;
243*21b96b63SSatoshi Sahara                $id = $this->info['id'];
2443d7df1dcSSatoshi Sahara                $diff = false;
2453d7df1dcSSatoshi Sahara
246*21b96b63SSatoshi Sahara                if (isset($this->info['media'])) {
247*21b96b63SSatoshi Sahara                    $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
248*21b96b63SSatoshi Sahara                    $diff = (count($revs) && file_exists(mediaFN($id)));
2493d7df1dcSSatoshi Sahara                    if ($diff) {
2503d7df1dcSSatoshi Sahara                        $href = media_managerURL(
251*21b96b63SSatoshi Sahara                            ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&'
2523d7df1dcSSatoshi Sahara                        );
2533d7df1dcSSatoshi Sahara                    }
2543d7df1dcSSatoshi Sahara                } else {
255*21b96b63SSatoshi Sahara                    $href = wl($id, "do=diff", false, '&');
2563d7df1dcSSatoshi Sahara                }
2573d7df1dcSSatoshi Sahara
258*21b96b63SSatoshi Sahara                if (isset($this->info['media']) && !$diff) {
259*21b96b63SSatoshi Sahara                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
2603d7df1dcSSatoshi Sahara                } else {
261*21b96b63SSatoshi Sahara                    $html = '<a href="'.$href.'" class="diff_link">'
262*21b96b63SSatoshi Sahara                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
263*21b96b63SSatoshi Sahara                          . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
264*21b96b63SSatoshi Sahara                          . '</a>';
2653d7df1dcSSatoshi Sahara                }
266*21b96b63SSatoshi Sahara                return $html;
267*21b96b63SSatoshi Sahara            }
2683d7df1dcSSatoshi Sahara
269*21b96b63SSatoshi Sahara            // icon revision link
270*21b96b63SSatoshi Sahara            public function revisionlink()
271*21b96b63SSatoshi Sahara            {
272*21b96b63SSatoshi Sahara                global $lang;
273*21b96b63SSatoshi Sahara                $id = $this->info['id'];
274*21b96b63SSatoshi Sahara                if (isset($this->info['media'])) {
275*21b96b63SSatoshi Sahara                    $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&');
2763d7df1dcSSatoshi Sahara                } else {
277*21b96b63SSatoshi Sahara                    $href = wl($id, "do=revisions", false, '&');
2783d7df1dcSSatoshi Sahara                }
279*21b96b63SSatoshi Sahara                $html = '<a href="'.$href.'" class="revisions_link">'
280*21b96b63SSatoshi Sahara                      . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
281*21b96b63SSatoshi Sahara                      . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
282*21b96b63SSatoshi Sahara                      . '</a>';
283*21b96b63SSatoshi Sahara                return $html;
284*21b96b63SSatoshi Sahara            }
2853d7df1dcSSatoshi Sahara
286*21b96b63SSatoshi Sahara            // name of the page or media file
287*21b96b63SSatoshi Sahara            public function itemName()
288*21b96b63SSatoshi Sahara            {
289*21b96b63SSatoshi Sahara                $id = $this->info['id'];
290*21b96b63SSatoshi Sahara                if (isset($this->info['media'])) {
291*21b96b63SSatoshi Sahara                    $href = media_managerURL(['tab_details'=>'view', 'image'=> $id, 'ns'=> getNS($id)], '&');
292*21b96b63SSatoshi Sahara                    $class = file_exists(mediaFN($id)) ? 'wikilink1' : 'wikilink2';
293*21b96b63SSatoshi Sahara                    $html = '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>';
2943d7df1dcSSatoshi Sahara                } else {
295*21b96b63SSatoshi Sahara                    $html = html_wikilink(':'.$id, (useHeading('navigation') ? null : $id));
2963d7df1dcSSatoshi Sahara                }
297*21b96b63SSatoshi Sahara                return $html;
298*21b96b63SSatoshi Sahara            }
2993d7df1dcSSatoshi Sahara
300*21b96b63SSatoshi Sahara            // edit summary
301*21b96b63SSatoshi Sahara            public function editSummary()
302*21b96b63SSatoshi Sahara            {
303*21b96b63SSatoshi Sahara                $html = '<span class="sum">';
304*21b96b63SSatoshi Sahara                $html.= ' – '. hsc($this->info['sum']);
305*21b96b63SSatoshi Sahara                $html.= '</span>';
306*21b96b63SSatoshi Sahara                return $html;
3073d7df1dcSSatoshi Sahara            }
308*21b96b63SSatoshi Sahara
309*21b96b63SSatoshi Sahara            // editor of the page or media file
310*21b96b63SSatoshi Sahara            public function editor()
311*21b96b63SSatoshi Sahara            {
312*21b96b63SSatoshi Sahara                $html = '<span class="user">';
313*21b96b63SSatoshi Sahara                if ($this->info['user']) {
314*21b96b63SSatoshi Sahara                    $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
315*21b96b63SSatoshi Sahara                    if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
3163d7df1dcSSatoshi Sahara                } else {
317*21b96b63SSatoshi Sahara                    $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
3183d7df1dcSSatoshi Sahara                }
319*21b96b63SSatoshi Sahara                $html.= '</span>';
320*21b96b63SSatoshi Sahara                return $html;
3213d7df1dcSSatoshi Sahara            }
322*21b96b63SSatoshi Sahara        }; // end of anonymous class (objRevInfo)
3233d7df1dcSSatoshi Sahara    }
3243d7df1dcSSatoshi Sahara
3253d7df1dcSSatoshi Sahara}
326