xref: /dokuwiki/inc/ChangeLog/RevisionInfo.php (revision 5c25a0714a8ef36fe8b57b70c8b59ee09eccaac1)
1<?php
2
3namespace dokuwiki\ChangeLog;
4
5/**
6 * Class RevisionInfo
7 *
8 * Provides methods to show Revision Information in DokuWiki Ui compoments:
9 *  - Ui\Recent
10 *  - Ui\PageRevisions
11 *  - Ui\MediaRevisions
12 */
13class RevisionInfo
14{
15    protected $info;
16
17    /**
18     * Constructor
19     *
20     * @param array $info Revision Infomation structure with entries:
21     *      - date:  unix timestamp
22     *      - ip:    IPv4 or IPv6 address
23     *      - type:  change type (log line type)
24     *      - id:    page id
25     *      - user:  user name
26     *      - sum:   edit summary (or action reason)
27     *      - extra: extra data (varies by line type)
28     *      - sizechange: change of filesize
29     *      additionally,
30     *      - current:   (optional) whether current revision or not
31     *      - timestamp: (optional) set only when external edits occurred
32     */
33    public function __construct(array $info)
34    {
35        $info['item'] = strrpos($info['id'], '.') ? 'media' : 'page';
36        // current is always true for items shown in Ui\Recents
37        $info['current'] = $info['current'] ?? true;
38        // revision info may have timestamp key when external edits occurred
39        $info['timestamp'] = $info['timestamp'] ?? true;
40
41        $this->info = $info;
42    }
43
44    /**
45     * fileicon of the page or media file
46     * used in [Ui\recent]
47     *
48     * @return string
49     */
50    public function itemIcon()
51    {
52        $id = $this->info['id'];
53        $html = '';
54        switch ($this->info['item']) {
55            case 'media': // media file revision
56                $html = media_printicon($id);
57                break;
58            case 'page': // page revision
59                $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
60        }
61        return $html;
62    }
63
64    /**
65     * edit date and time of the page or media file
66     * used in [Ui\recent, Ui\Revisions]
67     *
68     * @param bool $checkTimestamp  enable timestamp check, alter formatted string when timestamp is false
69     * @return string
70     */
71    public function editDate($checkTimestamp = false)
72    {
73        $formatted = dformat($this->info['date']);
74        if ($checkTimestamp && $this->info['timestamp'] === false) {
75            // exact date is unknown for item has externally deleted or older file restored
76            // when unknown, alter formatted string "YYYY-mm-DD HH:MM" to "____-__-__ __:__"
77            $formatted = preg_replace('/[0-9a-zA-Z]/','_', $formatted);
78        }
79        return '<span class="date">'. $formatted .'</span>';
80    }
81
82    /**
83     * edit summary
84     * used in [Ui\recent, Ui\Revisions]
85     *
86     * @return string
87     */
88    public function editSummary()
89    {
90        return '<span class="sum">'.' – '. hsc($this->info['sum']).'</span>';
91    }
92
93    /**
94     * editor of the page or media file
95     * used in [Ui\recent, Ui\Revisions]
96     *
97     * @return string
98     */
99    public function editor()
100    {
101        $html = '<span class="user">';
102        if ($this->info['user']) {
103            $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
104            if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
105        } else {
106            $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
107        }
108        $html.= '</span>';
109        return $html;
110    }
111
112    /**
113     * name of the page or media file
114     * used in [Ui\recent, Ui\Revisions]
115     *
116     * @return string
117     */
118    public function itemName()
119    {
120        $id = $this->info['id'];
121        $rev = ($this->info['current']) ? '' : $this->info['date'];
122
123        switch ($this->info['item']) {
124            case 'media': // media file revision
125                $params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id];
126                if ($rev) $params += ['rev'=> $rev];
127                $href = media_managerURL($params, '&');
128                if(file_exists(mediaFN($id, $rev))) {
129                    $class = 'wikilink1';
130                } else {
131                    $class = 'wikilink2';
132                    if(!$this->info['current']) {
133                        //revision is not in attic
134                        return $id;
135                    }
136                }
137                return '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>';
138            case 'page': // page revision
139                $params = $rev ? ['rev'=> $rev] : [];
140                $href = wl($id, $params, false, '&');
141                $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
142                if (!$display_name) $display_name = $id;
143                if(page_exists($id, $rev)) {
144                    $class = 'wikilink1';
145                } else {
146                    $class = 'wikilink2';
147                    if(!$this->info['current']) {
148                        //revision is not in attic
149                        return $display_name;
150                    }
151                }
152                return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
153        }
154
155        return '';
156    }
157
158    /**
159     * difflink icon in recents list
160     * all items in the recents are "current" revision of the page or media
161     *
162     * @return string
163     */
164    public function difflinkRecent()
165    {
166        global $lang;
167        $id = $this->info['id'];
168
169        $href = '';
170        switch ($this->info['item']) {
171            case 'media': // media file revision
172                $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
173                $showLink = (count($revs) && file_exists(mediaFN($id)));
174                if ($showLink) {
175                    $href = media_managerURL(
176                        ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&'
177                    );
178                }
179                break;
180            case 'page': // page revision
181                if($this->info['type'] !== DOKU_CHANGE_TYPE_CREATE) {
182                    $href = wl($id, "do=diff", false, '&');
183                }
184        }
185
186        if ($href) {
187            $html = '<a href="'.$href.'" class="diff_link">'
188                  . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
189                  . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
190                  . '</a>';
191        } else {
192            $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
193        }
194        return $html;
195    }
196
197    /**
198     * difflink icon in revsions list
199     * the icon does not displayed for the current revision
200     *
201     * @return string
202     */
203    public function difflinkRevision()
204    {
205        global $lang;
206        $id = $this->info['id'];
207        $rev = $this->info['date'];
208
209        switch ($this->info['item']) {
210            case 'media': // media file revision
211                if ($this->info['current'] || !file_exists(mediaFN($id, $rev))) {
212                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
213                } else {
214                    $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
215                    $html = '<a href="'.$href.'" class="diff_link">'
216                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
217                          . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
218                          . '</a> ';
219                }
220                return $html;
221            case 'page': // page revision
222                if ($this->info['current'] || !page_exists($id, $rev)) {
223                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
224                } else {
225                    $href = wl($id, "rev=$rev,do=diff", false, '&');
226                    $html = '<a href="'.$href.'" class="diff_link">'
227                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
228                          . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
229                          . '</a>';
230                }
231                return $html;
232        }
233        return '';
234    }
235
236    /**
237     * icon revision link
238     * used in [Ui\recent]
239     *
240     * @return string
241     */
242    public function revisionlink()
243    {
244        global $lang;
245
246        if (!actionOK('revisions')) {
247            return '';  //FIXME check page, media
248        }
249
250        $id = $this->info['id'];
251        $href = '';
252        switch ($this->info['item']) {
253            case 'media': // media file revision
254                $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&');
255                break;
256            case 'page': // page revision
257                $href = wl($id, "do=revisions", false, '&');
258        }
259        return '<a href="'.$href.'" class="revisions_link">'
260              . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
261              . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
262              . '</a>';
263    }
264
265    /**
266     * size change
267     * used in [Ui\recent, Ui\Revisions]
268     *
269     * @return string
270     */
271    public function sizeChange()
272    {
273        $class = 'sizechange';
274        $value = filesize_h(abs($this->info['sizechange']));
275        if ($this->info['sizechange'] > 0) {
276            $class .= ' positive';
277            $value = '+' . $value;
278        } elseif ($this->info['sizechange'] < 0) {
279            $class .= ' negative';
280            $value = '-' . $value;
281        } else {
282            $value = '±' . $value;
283        }
284        return '<span class="'.$class.'">'.$value.'</span>';
285    }
286
287    /**
288     * current indicator, used in revison list
289     * not used in Ui\Recents because recent items are always current one
290     *
291     * @return string
292     */
293    public function currentIndicator()
294    {
295        global $lang;
296        return ($this->info['current']) ? '('.$lang['current'].')' : '';
297    }
298
299
300}
301