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