xref: /dokuwiki/inc/ChangeLog/RevisionInfo.php (revision bf3fa5e922d3db442074aaf11737617daadd6f84)
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 revison 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 irems 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        switch ($this->info['item']) {
54            case 'media': // media file revision
55                $html = media_printicon($id);
56                break;
57            case 'page': // page revision
58                $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
59        }
60        return $html;
61    }
62
63    /**
64     * edit date and time of the page or media file
65     * used in [Ui\recent, Ui\Revisions]
66     *
67     * @param bool $checkTimestamp  enable timestamp check, alter formatted string when timestamp is false
68     * @return string
69     */
70    public function editDate($checkTimestamp = false)
71    {
72        global $lang;
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        global $lang;
102        $html = '<span class="user">';
103        if ($this->info['user']) {
104            $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
105            if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
106        } else {
107            $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
108        }
109        $html.= '</span>';
110        return $html;
111    }
112
113    /**
114     * name of the page or media file
115     * used in [Ui\recent, Ui\Revisions]
116     *
117     * @return string
118     */
119    public function itemName()
120    {
121        $id = $this->info['id'];
122        $rev = ($this->info['current']) ? '' : $this->info['date'];
123
124        switch ($this->info['item']) {
125            case 'media': // media file revision
126                $params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id];
127                if ($rev) $params += ['rev'=> $rev];
128                $href = media_managerURL($params, '&');
129                $class = file_exists(mediaFN($id, $rev)) ? 'wikilink1' : 'wikilink2';
130                return '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>';
131            case 'page': // page revision
132                $params = ($rev)  ? '' : "rev=$rev";
133                $href = wl($id, $params, false, '&');
134                $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
135                if (!$display_name) $display_name = $id;
136                $class = page_exists($id, $rev) ? 'wikilink1' : 'wikilink2';
137                if ($this->info['type'] == DOKU_CHANGE_TYPE_DELETE) {
138                    $class = 'wikilink2';
139                }
140                return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
141        }
142    }
143
144    /**
145     * difflink icon in recents list
146     * all items in the recents are "current" revision of the page or media
147     *
148     * @return string
149     */
150    public function difflinkRecent()
151    {
152        global $lang;
153        $id = $this->info['id'];
154
155        $href = '';
156        switch ($this->info['item']) {
157            case 'media': // media file revision
158                $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
159                $showLink = (count($revs) && file_exists(mediaFN($id)));
160                if ($showLink) {
161                    $href = media_managerURL(
162                        ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&'
163                    );
164                }
165                break;
166            case 'page': // page revision
167                if($this->info['type'] !== DOKU_CHANGE_TYPE_CREATE) {
168                    $href = wl($id, "do=diff", false, '&');
169                }
170        }
171
172        if ($href) {
173            $html = '<a href="'.$href.'" class="diff_link">'
174                  . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
175                  . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
176                  . '</a>';
177        } else {
178            $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
179        }
180        return $html;
181    }
182
183    /**
184     * difflink icon in revsions list
185     * the icon does not displayed for the current revision
186     *
187     * @return string
188     */
189    public function difflinkRevision()
190    {
191        global $lang;
192        $id = $this->info['id'];
193        $rev = $this->info['date'];
194
195        switch ($this->info['item']) {
196            case 'media': // media file revision
197                if ($this->info['current'] || !file_exists(mediaFN($id, $rev))) {
198                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
199                } else {
200                    $href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
201                    $html = '<a href="'.$href.'" class="diff_link">'
202                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
203                          . ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
204                          . '</a> ';
205                }
206                return $html;
207            case 'page': // page revision
208                if ($this->info['current'] || !page_exists($id, $rev)) {
209                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
210                } else {
211                    $href = wl($id, "rev=$rev,do=diff", false, '&');
212                    $html = '<a href="'.$href.'" class="diff_link">'
213                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
214                          . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
215                          . '</a>';
216                }
217                return $html;
218        }
219        return '';
220    }
221
222    /**
223     * icon revision link
224     * used in [Ui\recent]
225     *
226     * @return string
227     */
228    public function revisionlink()
229    {
230        global $lang, $conf;
231
232        if (!actionOK('revisions')) {
233            return '';  //FIXME check page, media
234        }
235
236        $id = $this->info['id'];
237        switch ($this->info['item']) {
238            case 'media': // media file revision
239                $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&');
240                break;
241            case 'page': // page revision
242                $href = wl($id, "do=revisions", false, '&');
243        }
244        return '<a href="'.$href.'" class="revisions_link">'
245              . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
246              . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
247              . '</a>';
248    }
249
250    /**
251     * size change
252     * used in [Ui\recent, Ui\Revisions]
253     *
254     * @return string
255     */
256    public function sizeChange()
257    {
258        $class = 'sizechange';
259        $value = filesize_h(abs($this->info['sizechange']));
260        if ($this->info['sizechange'] > 0) {
261            $class .= ' positive';
262            $value = '+' . $value;
263        } elseif ($this->info['sizechange'] < 0) {
264            $class .= ' negative';
265            $value = '-' . $value;
266        } else {
267            $value = '±' . $value;
268        }
269        return '<span class="'.$class.'">'.$value.'</span>';
270    }
271
272    /**
273     * current indicator, used in revison list
274     * not used in Ui\Recents because recent items are always current one
275     *
276     * @return string
277     */
278    public function currentIndicator()
279    {
280        global $lang;
281        return ($this->info['current']) ? '('.$lang['current'].')' : '';
282    }
283
284
285}
286