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