codestyle adjustments: function argument spacing
[dokuwiki.git] / inc / ChangeLog / RevisionInfo.php
blobedbc2d7add5f680de771a5393b8dcfa80d84e39e
1 <?php
3 namespace dokuwiki\ChangeLog;
5 /**
6 * Class RevisionInfo
8 * Provides methods to show Revision Information in DokuWiki Ui components:
9 * - Ui\Recent
10 * - Ui\PageRevisions
11 * - Ui\MediaRevisions
13 class RevisionInfo
15 /* @var array */
16 protected $info;
18 /**
19 * Constructor
21 * @param array $info Revision Information structure with entries:
22 * - date: unix timestamp
23 * - ip: IPv4 or IPv6 address
24 * - type: change type (log line type)
25 * - id: page id
26 * - user: user name
27 * - sum: edit summary (or action reason)
28 * - extra: extra data (varies by line type)
29 * - sizechange: change of filesize
30 * additionally,
31 * - current: (optional) whether current revision or not
32 * - timestamp: (optional) set only when external edits occurred
33 * - mode: (internal use) ether "media" or "page"
35 public function __construct($info = null)
37 if (is_array($info) && isset($info['id'])) {
38 // define strategy context
39 $info['mode'] = $info['media'] ? 'media' : 'page';
40 } else {
41 $info = [
42 'mode' => 'page',
43 'date' => false,
46 $this->info = $info;
49 /**
50 * Set or return whether this revision is current page or media file
52 * This method does not check exactly whether the revision is current or not. Instead,
53 * set value of associated "current" key for internal use. Some UI element like diff
54 * link button depend on relation to current page or media file. A changelog line does
55 * not indicate whether it corresponds to current page or media file.
57 * @param bool $value true if the revision is current, otherwise false
58 * @return bool
60 public function isCurrent($value = null)
62 return (bool) $this->val('current', $value);
65 /**
66 * Return or set a value of associated key of revision information
67 * but does not allow to change values of existing keys
69 * @param string $key
70 * @param mixed $value
71 * @return string|null
73 public function val($key, $value = null)
75 if (isset($value) && !array_key_exists($key, $this->info)) {
76 // setter, only for new keys
77 $this->info[$key] = $value;
79 if (array_key_exists($key, $this->info)) {
80 // getter
81 return $this->info[$key];
83 return null;
86 /**
87 * Set extra key-value to the revision information
88 * but does not allow to change values of existing keys
89 * @param array $info
90 * @return void
92 public function append(array $info)
94 foreach ($info as $key => $value) {
95 $this->val($key, $value);
101 * file icon of the page or media file
102 * used in [Ui\recent]
104 * @return string
106 public function showFileIcon()
108 $id = $this->val('id');
109 if ($this->val('mode') == 'media') {
110 // media file revision
111 return media_printicon($id);
112 } elseif ($this->val('mode') == 'page') {
113 // page revision
114 return '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
119 * edit date and time of the page or media file
120 * used in [Ui\recent, Ui\Revisions]
122 * @param bool $checkTimestamp enable timestamp check, alter formatted string when timestamp is false
123 * @return string
125 public function showEditDate($checkTimestamp = false)
127 $formatted = dformat($this->val('date'));
128 if ($checkTimestamp && $this->val('timestamp') === false) {
129 // exact date is unknown for externally deleted file
130 // when unknown, alter formatted string "YYYY-mm-DD HH:MM" to "____-__-__ __:__"
131 $formatted = preg_replace('/[0-9a-zA-Z]/', '_', $formatted);
133 return '<span class="date">'. $formatted .'</span>';
137 * edit summary
138 * used in [Ui\recent, Ui\Revisions]
140 * @return string
142 public function showEditSummary()
144 return '<span class="sum">'.' – '. hsc($this->val('sum')).'</span>';
148 * editor of the page or media file
149 * used in [Ui\recent, Ui\Revisions]
151 * @return string
153 public function showEditor()
155 if ($this->val('user')) {
156 $html = '<bdi>'. editorinfo($this->val('user')) .'</bdi>';
157 if (auth_ismanager()) $html .= ' <bdo dir="ltr">('. $this->val('ip') .')</bdo>';
158 } else {
159 $html = '<bdo dir="ltr">'. $this->val('ip') .'</bdo>';
161 return '<span class="user">'. $html. '</span>';
165 * name of the page or media file
166 * used in [Ui\recent, Ui\Revisions]
168 * @return string
170 public function showFileName()
172 $id = $this->val('id');
173 $rev = $this->isCurrent() ? '' : $this->val('date');
175 if ($this->val('mode') == 'media') {
176 // media file revision
177 $params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id];
178 if ($rev) $params += ['rev'=> $rev];
179 $href = media_managerURL($params, '&');
180 $display_name = $id;
181 $exists = file_exists(mediaFN($id, $rev));
182 } elseif ($this->val('mode') == 'page') {
183 // page revision
184 $params = $rev ? ['rev'=> $rev] : [];
185 $href = wl($id, $params, false, '&');
186 $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
187 if (!$display_name) $display_name = $id;
188 $exists = page_exists($id, $rev);
191 if ($exists) {
192 $class = 'wikilink1';
193 } elseif ($this->isCurrent()) {
194 //show only not-existing link for current page, which allows for directly create a new page/upload
195 $class = 'wikilink2';
196 } else {
197 //revision is not in attic
198 return $display_name;
200 if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
201 $class = 'wikilink2';
203 return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
207 * Revision Title for PageDiff table headline
209 * @return string
211 public function showRevisionTitle()
213 global $lang;
215 if (!$this->val('date')) return '&mdash;';
217 $id = $this->val('id');
218 $rev = $this->isCurrent() ? '' : $this->val('date');
219 $params = ($rev) ? ['rev'=> $rev] : [];
221 // revision info may have timestamp key when external edits occurred
222 $date = ($this->val('timestamp') === false)
223 ? $lang['unknowndate']
224 : dformat($this->val('date'));
227 if ($this->val('mode') == 'media') {
228 // media file revision
229 $href = ml($id, $params, false, '&');
230 $exists = file_exists(mediaFN($id, $rev));
231 } elseif ($this->val('mode') == 'page') {
232 // page revision
233 $href = wl($id, $params, false, '&');
234 $exists = page_exists($id, $rev);
236 if ($exists) {
237 $class = 'wikilink1';
238 } elseif ($this->isCurrent()) {
239 //show only not-existing link for current page, which allows for directly create a new page/upload
240 $class = 'wikilink2';
241 } else {
242 //revision is not in attic
243 return $id.' ['.$date.']';
245 if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
246 $class = 'wikilink2';
248 return '<bdi><a class="'.$class.'" href="'.$href.'">'.$id.' ['.$date.']'.'</a></bdi>';
252 * diff link icon in recent changes list, to compare (this) current revision with previous one
253 * all items in "recent changes" are current revision of the page or media
255 * @return string
257 public function showIconCompareWithPrevious()
259 global $lang;
260 $id = $this->val('id');
262 $href = '';
263 if ($this->val('mode') == 'media') {
264 // media file revision
265 // unlike page, media file does not copied to media_attic when uploaded.
266 // diff icon will not be shown when external edit occurred
267 // because no attic file to be compared with current.
268 $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
269 $showLink = (count($revs) && file_exists(mediaFN($id, $revs[0])) && file_exists(mediaFN($id)));
270 if ($showLink) {
271 $param = ['tab_details'=>'history', 'mediado'=>'diff', 'ns'=> getNS($id), 'image'=> $id];
272 $href = media_managerURL($param, '&');
274 } elseif ($this->val('mode') == 'page') {
275 // page revision
276 // when a page just created anyway, it is natural to expect no older revisions
277 // even if it had once existed but deleted before. Simply ignore to check changelog.
278 if ($this->val('type') !== DOKU_CHANGE_TYPE_CREATE) {
279 $href = wl($id, ['do'=>'diff'], false, '&');
283 if ($href) {
284 return '<a href="'.$href.'" class="diff_link">'
285 .'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
286 .' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
287 .'</a>';
288 } else {
289 return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
294 * diff link icon in revisions list, compare this revision with current one
295 * the icon does not displayed for the current revision
297 * @return string
299 public function showIconCompareWithCurrent()
301 global $lang;
302 $id = $this->val('id');
303 $rev = $this->isCurrent() ? '' : $this->val('date');
305 $href = '';
306 if ($this->val('mode') == 'media') {
307 // media file revision
308 if (!$this->isCurrent() && file_exists(mediaFN($id, $rev))) {
309 $param = ['mediado'=>'diff', 'image'=> $id, 'rev'=> $rev];
310 $href = media_managerURL($param, '&');
312 } elseif ($this->val('mode') == 'page') {
313 // page revision
314 if (!$this->isCurrent()) {
315 $href = wl($id, ['rev'=> $rev, 'do'=>'diff'], false, '&');
319 if ($href) {
320 return '<a href="'.$href.'" class="diff_link">'
321 .'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
322 .' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
323 .'</a>';
324 } else {
325 return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
330 * icon for revision action
331 * used in [Ui\recent]
333 * @return string
335 public function showIconRevisions()
337 global $lang;
339 if (!actionOK('revisions')) {
340 return '';
343 $id = $this->val('id');
344 if ($this->val('mode') == 'media') {
345 // media file revision
346 $param = ['tab_details'=>'history', 'ns'=> getNS($id), 'image'=> $id];
347 $href = media_managerURL($param, '&');
348 } elseif ($this->val('mode') == 'page') {
349 // page revision
350 $href = wl($id, ['do'=>'revisions'], false, '&');
352 return '<a href="'.$href.'" class="revisions_link">'
353 . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
354 . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
355 . '</a>';
359 * size change
360 * used in [Ui\recent, Ui\Revisions]
362 * @return string
364 public function showSizeChange()
366 $class = 'sizechange';
367 $value = filesize_h(abs($this->val('sizechange')));
368 if ($this->val('sizechange') > 0) {
369 $class .= ' positive';
370 $value = '+' . $value;
371 } elseif ($this->val('sizechange') < 0) {
372 $class .= ' negative';
373 $value = '-' . $value;
374 } else {
375 $value = '±' . $value;
377 return '<span class="'.$class.'">'.$value.'</span>';
381 * current indicator, used in revision list
382 * not used in Ui\Recent because recent files are always current one
384 * @return string
386 public function showCurrentIndicator()
388 global $lang;
389 return $this->isCurrent() ? '('.$lang['current'].')' : '';