1<?php 2 3namespace dokuwiki\Ui; 4 5use dokuwiki\ChangeLog\PageChangeLog; 6use dokuwiki\ChangeLog\MediaChangeLog; 7 8/** 9 * DokuWiki Diff Interface 10 * parent class of PageDiff and MediaDiff 11 * 12 * @package dokuwiki\Ui 13 */ 14abstract class Diff extends Ui 15{ 16 /* @var string */ 17 protected $id; // page id or media id 18 19 /* @var int */ 20 protected $old_rev; // older revision, timestamp of left side 21 protected $new_rev; // newer revision, timestamp of right side 22 23 /* @var array */ 24 protected $preference = []; 25 26 /* @var ChangeLog */ 27 protected $changelog; // PageChangeLog or MediaChangeLog object 28 29 /** 30 * Diff Ui constructor 31 * 32 * @param string $id page id or media id 33 */ 34 public function __construct($id) 35 { 36 $this->id = $id; 37 $this->setChangeLog(); 38 } 39 40 /** 41 * set class property changelog 42 */ 43 abstract protected function setChangeLog(); 44 45 /** 46 * Set a pair of revisions to be compared 47 * 48 * @param int $old_rev 49 * @param int $new_rev 50 * @return $this 51 */ 52 public function compare($old_rev, $new_rev) 53 { 54 $this->old_rev = $old_rev; 55 $this->new_rev = $new_rev; 56 return $this; 57 } 58 59 /** 60 * Gets or Sets preference of the Ui\Diff object 61 * 62 * @param string|array $prefs a key name or key-value pair(s) 63 * @param mixed $value value used when the first args is string 64 * @return array|$this 65 */ 66 public function preference($prefs = null, $value = null) 67 { 68 // set 69 if (is_string($prefs) && isset($value)) { 70 $this->preference[$prefs] = $value; 71 return $this; 72 } elseif (is_array($prefs)) { 73 foreach ($prefs as $name => $value) { 74 $this->preference[$name] = $value; 75 } 76 return $this; 77 } 78 // get 79 return $this->preference; 80 } 81 82 /** 83 * Retrieve requested revision(s) and difftype from Ui\Revisions 84 * 85 * @return void 86 */ 87 protected function preProcess() 88 { 89 global $INPUT; 90 91 // difflink icon click, eg. ?rev=123456789&do=diff 92 if ($INPUT->has('rev')) { 93 $this->old_rev = $INPUT->int('rev'); 94 $this->new_rev = ''; // current revision 95 } 96 97 // submit button with two checked boxes 98 $rev2 = $INPUT->arr('rev2', []); 99 if (count($rev2) > 1) { 100 if ($rev2[0] == 'current') { 101 [$this->old_rev, $this->new_rev] = [$rev2[1], '']; 102 } elseif ($rev2[1] == 'current') { 103 [$this->old_rev, $this->new_rev] = [$rev2[0], '']; 104 } elseif ($rev2[0] < $rev2[1]) { 105 [$this->old_rev, $this->new_rev] = [$rev2[0], $rev2[1]]; 106 } else { 107 [$this->old_rev, $this->new_rev] = [$rev2[1], $rev2[0]]; 108 } 109 } 110 111 // diff view type 112 if ($INPUT->has('difftype')) { 113 // retrieve requested $difftype 114 $this->preference['difftype'] = $INPUT->str('difftype'); 115 } else { 116 // read preference from DokuWiki cookie. PageDiff only 117 get_doku_pref('difftype', $mode); 118 if (isset($mode)) $this->preference['difftype'] = $mode; 119 } 120 } 121 122 123 124 /** 125 * Build header of diff HTML 126 * 127 * @param string $l_rev Left revisions 128 * @param string $r_rev Right revision 129 * @return string[] HTML snippets for diff header 130 */ 131 public function buildDiffHead($l_rev, $r_rev) 132 { 133 global $lang; 134 135 // detect PageDiff or MediaDiff 136 switch (get_class($this->changelog)) { 137 case PageChangeLog::class : 138 $media_or_wikiFN = 'wikiFN'; 139 $ml_or_wl = 'wl'; 140 $media = false; 141 break; 142 case MediaChangeLog::class : 143 $media_or_wikiFN = 'mediaFN'; 144 $ml_or_wl = 'ml'; 145 $media = true; 146 break; 147 } 148 149 $head_separator = ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 150 $l_minor = $r_minor = ''; 151 152 // left side 153 if (!$l_rev) { 154 $l_head = '—'; 155 } else { 156 $l_info = $this->changelog->getRevisionInfo($l_rev); 157 if ($l_info['user']) { 158 $l_user = '<bdi>'.editorinfo($l_info['user']).'</bdi>'; 159 if (auth_ismanager()) $l_user .= ' <bdo dir="ltr">('.$l_info['ip'].')</bdo>'; 160 } else { 161 $l_user = '<bdo dir="ltr">'.$l_info['ip'].'</bdo>'; 162 } 163 $l_user = '<span class="user">'.$l_user.'</span>'; 164 $l_sum = ($l_info['sum']) ? '<span class="sum"><bdi>'.hsc($l_info['sum']).'</bdi></span>' : ''; 165 if ($l_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $l_minor = 'class="minor"'; 166 167 $l_head_title = ($media) ? dformat($l_rev) : $this->id.' ['.dformat($l_rev).']'; 168 $l_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id,"rev=$l_rev").'">' 169 . $l_head_title.'</a></bdi>'.$head_separator.$l_user.' '.$l_sum; 170 } 171 172 // right side 173 if ($r_rev) { 174 $r_info = $this->changelog->getRevisionInfo($r_rev); 175 if ($r_info['user']) { 176 $r_user = '<bdi>'.editorinfo($r_info['user']).'</bdi>'; 177 if (auth_ismanager()) $r_user .= ' <bdo dir="ltr">('.$r_info['ip'].')</bdo>'; 178 } else { 179 $r_user = '<bdo dir="ltr">'.$r_info['ip'].'</bdo>'; 180 } 181 $r_user = '<span class="user">'.$r_user.'</span>'; 182 $r_sum = ($r_info['sum']) ? '<span class="sum"><bdi>'.hsc($r_info['sum']).'</bdi></span>' : ''; 183 if ($r_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"'; 184 185 $r_head_title = ($media) ? dformat($r_rev) : $this->id.' ['.dformat($r_rev).']'; 186 $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id,"rev=$r_rev").'">' 187 . $r_head_title.'</a></bdi>'.$head_separator.$r_user.' '.$r_sum; 188 } elseif ($_rev = @filemtime($media_or_wikiFN($this->id))) { 189 $_info = $this->changelog->getRevisionInfo($_rev); 190 if ($_info['user']) { 191 $_user = '<bdi>'.editorinfo($_info['user']).'</bdi>'; 192 if (auth_ismanager()) $_user .= ' <bdo dir="ltr">('.$_info['ip'].')</bdo>'; 193 } else { 194 $_user = '<bdo dir="ltr">'.$_info['ip'].'</bdo>'; 195 } 196 $_user = '<span class="user">'.$_user.'</span>'; 197 $_sum = ($_info['sum']) ? '<span class="sum"><bdi>'.hsc($_info['sum']).'</span></bdi>' : ''; 198 if ($_info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) $r_minor = 'class="minor"'; 199 200 $r_head_title = ($media) ? dformat($_rev) : $this->id.' ['.dformat($_rev).']'; 201 $r_head = '<bdi><a class="wikilink1" href="'.$ml_or_wl($this->id).'">' 202 . $r_head_title.'</a></bdi> '.'('.$lang['current'].')'.$head_separator.$_user.' '.$_sum; 203 } else { 204 $r_head = '— ('.$lang['current'].')'; 205 } 206 207 return array($l_head, $r_head, $l_minor, $r_minor); 208 } 209 210} 211