163ab9afeSSatoshi Sahara<?php 263ab9afeSSatoshi Sahara 363ab9afeSSatoshi Saharanamespace dokuwiki\Ui; 463ab9afeSSatoshi Sahara 563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog; 6d9c75b22SSatoshi Saharause dokuwiki\Ui\MediaRevisions; 763ab9afeSSatoshi Saharause dokuwiki\Extension\Event; 863ab9afeSSatoshi Saharause dokuwiki\Form\Form; 930a159abSSatoshi Saharause JpegMeta; 1063ab9afeSSatoshi Sahara 1163ab9afeSSatoshi Sahara/** 1263ab9afeSSatoshi Sahara * DokuWiki MediaDiff Interface 1363ab9afeSSatoshi Sahara * 1463ab9afeSSatoshi Sahara * @package dokuwiki\Ui 1563ab9afeSSatoshi Sahara */ 1663ab9afeSSatoshi Saharaclass MediaDiff extends Diff 1763ab9afeSSatoshi Sahara{ 18d9c75b22SSatoshi Sahara /* @var MediaChangeLog */ 19d9c75b22SSatoshi Sahara protected $changelog; 20d9c75b22SSatoshi Sahara 21*0ea1f71bSSatoshi Sahara /* @var array */ 22*0ea1f71bSSatoshi Sahara protected $oldRevInfo; 23*0ea1f71bSSatoshi Sahara protected $newRevInfo; 24*0ea1f71bSSatoshi Sahara 25*0ea1f71bSSatoshi Sahara /* @var bool */ 26*0ea1f71bSSatoshi Sahara protected $is_img; 27*0ea1f71bSSatoshi Sahara 2863ab9afeSSatoshi Sahara /** 2963ab9afeSSatoshi Sahara * MediaDiff Ui constructor 3063ab9afeSSatoshi Sahara * 31edb50e6aSSatoshi Sahara * @param string $id media id 3263ab9afeSSatoshi Sahara */ 33edb50e6aSSatoshi Sahara public function __construct($id) 3463ab9afeSSatoshi Sahara { 354557f463SSatoshi Sahara if (!isset($id)) { 3630a159abSSatoshi Sahara throw new \InvalidArgumentException('media id should not be empty!'); 3730a159abSSatoshi Sahara } 38edb50e6aSSatoshi Sahara 39295564cdSSatoshi Sahara // init preference 40edb50e6aSSatoshi Sahara $this->preference['fromAjax'] = false; // see doluwiki\Ajax::callMediadiff() 41edb50e6aSSatoshi Sahara $this->preference['showIntro'] = false; 42*0ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions 438068440fSSatoshi Sahara 4430a159abSSatoshi Sahara parent::__construct($id); 458068440fSSatoshi Sahara } 468068440fSSatoshi Sahara 478068440fSSatoshi Sahara /** @inheritdoc */ 488068440fSSatoshi Sahara protected function setChangeLog() 498068440fSSatoshi Sahara { 508068440fSSatoshi Sahara $this->changelog = new MediaChangeLog($this->id); 5163ab9afeSSatoshi Sahara } 5263ab9afeSSatoshi Sahara 53*0ea1f71bSSatoshi Sahara /** 54*0ea1f71bSSatoshi Sahara * Handle requested revision(s) and diff view preferences 55*0ea1f71bSSatoshi Sahara * 56*0ea1f71bSSatoshi Sahara * @return void 57*0ea1f71bSSatoshi Sahara */ 58*0ea1f71bSSatoshi Sahara protected function handle() 59b4b4c5c6SSatoshi Sahara { 60*0ea1f71bSSatoshi Sahara global $INPUT; 61*0ea1f71bSSatoshi Sahara 62*0ea1f71bSSatoshi Sahara // requested rev or rev2 63*0ea1f71bSSatoshi Sahara parent::handle(); 64*0ea1f71bSSatoshi Sahara 65*0ea1f71bSSatoshi Sahara // requested diff view type 66*0ea1f71bSSatoshi Sahara if ($INPUT->has('difftype')) { 67*0ea1f71bSSatoshi Sahara $this->preference['difftype'] = $INPUT->str('difftype'); 68*0ea1f71bSSatoshi Sahara } 69*0ea1f71bSSatoshi Sahara 703d0f231eSSatoshi Sahara if (!isset($this->oldRev, $this->newRev)) { 71b4b4c5c6SSatoshi Sahara // no revision was given, compare previous to current 720a475154SSatoshi Sahara $changelog =& $this->changelog; 730a475154SSatoshi Sahara $this->oldRev = $changelog->getRevisions(0, 1)[0]; 740a475154SSatoshi Sahara $this->newRev = $changelog->currentRevision(); 75b4b4c5c6SSatoshi Sahara } 76b4b4c5c6SSatoshi Sahara } 77b4b4c5c6SSatoshi Sahara 7863ab9afeSSatoshi Sahara /** 79*0ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 80*0ea1f71bSSatoshi Sahara */ 81*0ea1f71bSSatoshi Sahara protected function preProcess() 82*0ea1f71bSSatoshi Sahara { 83*0ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 84*0ea1f71bSSatoshi Sahara 85*0ea1f71bSSatoshi Sahara // revision info of older file (left side) 86*0ea1f71bSSatoshi Sahara $this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev); 87*0ea1f71bSSatoshi Sahara // revision info of newer file (right side) 88*0ea1f71bSSatoshi Sahara $this->newRevInfo = $changelog->getRevisionInfo($this->newRev); 89*0ea1f71bSSatoshi Sahara 90*0ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 91*0ea1f71bSSatoshi Sahara 92*0ea1f71bSSatoshi Sahara foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { 93*0ea1f71bSSatoshi Sahara // use timestamp and '' properly as $rev for the current file 94*0ea1f71bSSatoshi Sahara $revInfo['rev'] = isset($revInfo['current']) ? '' : $revInfo['date']; 95*0ea1f71bSSatoshi Sahara $rev = $revInfo['rev']; 96*0ea1f71bSSatoshi Sahara 97*0ea1f71bSSatoshi Sahara // headline in the Diff view navigation 98*0ea1f71bSSatoshi Sahara $revInfo['navTitle'] = $this->revisionTitle($revInfo); 99*0ea1f71bSSatoshi Sahara 100*0ea1f71bSSatoshi Sahara if ($this->is_img) { 101*0ea1f71bSSatoshi Sahara $meta = new JpegMeta(mediaFN($this->id, $rev)); 102*0ea1f71bSSatoshi Sahara // get image width and height for the mediamanager preview panel 103*0ea1f71bSSatoshi Sahara $revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta); 104*0ea1f71bSSatoshi Sahara } 105*0ea1f71bSSatoshi Sahara } 106*0ea1f71bSSatoshi Sahara unset($revInfo); 107*0ea1f71bSSatoshi Sahara 108*0ea1f71bSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 109*0ea1f71bSSatoshi Sahara $this->is_img = ($this->is_img 110*0ea1f71bSSatoshi Sahara && ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30 111*0ea1f71bSSatoshi Sahara && ($this->newRevInfo['previewSize'][0] ?? 0) >= 30 112*0ea1f71bSSatoshi Sahara ); 113*0ea1f71bSSatoshi Sahara // adjust requested diff view type 114*0ea1f71bSSatoshi Sahara if (!$this->is_img) { 115*0ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; 116*0ea1f71bSSatoshi Sahara } 117*0ea1f71bSSatoshi Sahara } 118*0ea1f71bSSatoshi Sahara 119*0ea1f71bSSatoshi Sahara 120*0ea1f71bSSatoshi Sahara /** 12163ab9afeSSatoshi Sahara * Shows difference between two revisions of media 122675f74fbSSatoshi Sahara * 123675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 12463ab9afeSSatoshi Sahara */ 125309aaee5SSatoshi Sahara public function show() 12663ab9afeSSatoshi Sahara { 127675f74fbSSatoshi Sahara global $conf; 128675f74fbSSatoshi Sahara 12963ab9afeSSatoshi Sahara $ns = getNS($this->id); 13063ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 131675f74fbSSatoshi Sahara 132675f74fbSSatoshi Sahara if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return ''; 133675f74fbSSatoshi Sahara 134*0ea1f71bSSatoshi Sahara // retrieve form parameters: rev, rev2, difftype 135*0ea1f71bSSatoshi Sahara $this->handle(); 136*0ea1f71bSSatoshi Sahara // prepare revision info of comparison pair 137*0ea1f71bSSatoshi Sahara $this->preProcess(); 138675f74fbSSatoshi Sahara 139675f74fbSSatoshi Sahara // display intro 140675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 141675f74fbSSatoshi Sahara 142675f74fbSSatoshi Sahara // print form to choose diff view type 143*0ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 14491e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 145675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 146675f74fbSSatoshi Sahara } 147675f74fbSSatoshi Sahara 148309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 149675f74fbSSatoshi Sahara case 'opacity': 150675f74fbSSatoshi Sahara case 'portions': 151*0ea1f71bSSatoshi Sahara $this->showImageDiff(); 152675f74fbSSatoshi Sahara break; 153675f74fbSSatoshi Sahara case 'both': 154675f74fbSSatoshi Sahara default: 155*0ea1f71bSSatoshi Sahara $this->showFileDiff(); 156675f74fbSSatoshi Sahara break; 157675f74fbSSatoshi Sahara } 158675f74fbSSatoshi Sahara 159*0ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 160675f74fbSSatoshi Sahara echo '</div>'; 161675f74fbSSatoshi Sahara } 1622db397b2SSatoshi Sahara } 1632db397b2SSatoshi Sahara 1642db397b2SSatoshi Sahara /** 165675f74fbSSatoshi Sahara * Print form to choose diff view type 166675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1672db397b2SSatoshi Sahara */ 16891e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1692db397b2SSatoshi Sahara { 170*0ea1f71bSSatoshi Sahara // use timestamp for current revision 171*0ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; 172*0ea1f71bSSatoshi Sahara 17391e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 17491e70b5fSSatoshi Sahara 1752db397b2SSatoshi Sahara $form = new Form([ 1762db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1772db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1782db397b2SSatoshi Sahara 'method' => 'get', 1792db397b2SSatoshi Sahara 'class' => 'diffView', 1802db397b2SSatoshi Sahara ]); 1812db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1822db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1832db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 184*0ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[0]', $oldRev); 185*0ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[1]', $newRev); 1862db397b2SSatoshi Sahara $form->addTagClose('div'); 1872db397b2SSatoshi Sahara echo $form->toHTML(); 18891e70b5fSSatoshi Sahara 18991e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1902db397b2SSatoshi Sahara } 1912db397b2SSatoshi Sahara 192675f74fbSSatoshi Sahara /** 193675f74fbSSatoshi Sahara * Prints two images side by side 194675f74fbSSatoshi Sahara * and slider 195675f74fbSSatoshi Sahara * 196675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 197675f74fbSSatoshi Sahara */ 198*0ea1f71bSSatoshi Sahara protected function showImageDiff() 199675f74fbSSatoshi Sahara { 200*0ea1f71bSSatoshi Sahara // diff view type: opacity or portions 201675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 202*0ea1f71bSSatoshi Sahara 203*0ea1f71bSSatoshi Sahara // use '' for current revision 204*0ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 205675f74fbSSatoshi Sahara 206675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 207*0ea1f71bSSatoshi Sahara $oldRevSize = $this->oldRevInfo['previewSize']; 208*0ea1f71bSSatoshi Sahara $newRevSize = $this->newRevInfo['previewSize']; 2093d0f231eSSatoshi Sahara if ($oldRevSize != $newRevSize) { 2103d0f231eSSatoshi Sahara if ($newRevSize[0] > $oldRevSize[0]) { 2113d0f231eSSatoshi Sahara $oldRevSize = $newRevSize; 2122db397b2SSatoshi Sahara } 2132db397b2SSatoshi Sahara } 2142db397b2SSatoshi Sahara 2153d0f231eSSatoshi Sahara $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 2163d0f231eSSatoshi Sahara $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 217675f74fbSSatoshi Sahara 218675f74fbSSatoshi Sahara // slider 2193d0f231eSSatoshi Sahara echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; 220675f74fbSSatoshi Sahara 221675f74fbSSatoshi Sahara // two images in divs 222675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2233d0f231eSSatoshi Sahara echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; 2243d0f231eSSatoshi Sahara echo '<img src="'.$oldRevSrc.'" alt="" />'; 225675f74fbSSatoshi Sahara echo '</div>'; 2263d0f231eSSatoshi Sahara echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; 2273d0f231eSSatoshi Sahara echo '<img src="'.$newRevSrc.'" alt="" />'; 228675f74fbSSatoshi Sahara echo '</div>'; 229675f74fbSSatoshi Sahara echo '</div>'; 230675f74fbSSatoshi Sahara } 231675f74fbSSatoshi Sahara 232675f74fbSSatoshi Sahara /** 233675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 234675f74fbSSatoshi Sahara * 235675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 236675f74fbSSatoshi Sahara */ 237*0ea1f71bSSatoshi Sahara protected function showFileDiff() 238675f74fbSSatoshi Sahara { 239a6dd7f90SSatoshi Sahara global $lang; 24064876922SSatoshi Sahara $changelog =& $this->changelog; 241a6dd7f90SSatoshi Sahara 242*0ea1f71bSSatoshi Sahara $ns = getNS($this->id); 243*0ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 244*0ea1f71bSSatoshi Sahara 245*0ea1f71bSSatoshi Sahara // use '' for current revision 246*0ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 247*0ea1f71bSSatoshi Sahara 248*0ea1f71bSSatoshi Sahara $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); 249*0ea1f71bSSatoshi Sahara $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); 2502db397b2SSatoshi Sahara 251179b4660SSatoshi Sahara // display diff view table 2522db397b2SSatoshi Sahara echo '<div class="table">'; 2532db397b2SSatoshi Sahara echo '<table>'; 2542db397b2SSatoshi Sahara echo '<tr>'; 255*0ea1f71bSSatoshi Sahara echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>'; 256*0ea1f71bSSatoshi Sahara echo '<th>'. $this->newRevInfo['navTitle'] .'</th>'; 257675f74fbSSatoshi Sahara echo '</tr>'; 2582db397b2SSatoshi Sahara 2592db397b2SSatoshi Sahara echo '<tr class="image">'; 2602db397b2SSatoshi Sahara echo '<td>'; 2613d0f231eSSatoshi Sahara media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? 2622db397b2SSatoshi Sahara echo '</td>'; 2632db397b2SSatoshi Sahara 2642db397b2SSatoshi Sahara echo '<td>'; 2653d0f231eSSatoshi Sahara media_preview($this->id, $auth, $newRev, $newRevMeta); 2662db397b2SSatoshi Sahara echo '</td>'; 267675f74fbSSatoshi Sahara echo '</tr>'; 2682db397b2SSatoshi Sahara 2692db397b2SSatoshi Sahara echo '<tr class="actions">'; 2702db397b2SSatoshi Sahara echo '<td>'; 2713d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() 2722db397b2SSatoshi Sahara echo '</td>'; 2732db397b2SSatoshi Sahara 2742db397b2SSatoshi Sahara echo '<td>'; 2753d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $newRev); 2762db397b2SSatoshi Sahara echo '</td>'; 277675f74fbSSatoshi Sahara echo '</tr>'; 2782db397b2SSatoshi Sahara 2793d0f231eSSatoshi Sahara $l_tags = media_file_tags($oldRevMeta); 2803d0f231eSSatoshi Sahara $r_tags = media_file_tags($newRevMeta); 2812db397b2SSatoshi Sahara // FIXME r_tags-only stuff 2822db397b2SSatoshi Sahara foreach ($l_tags as $key => $l_tag) { 2832db397b2SSatoshi Sahara if ($l_tag['value'] != $r_tags[$key]['value']) { 2842db397b2SSatoshi Sahara $r_tags[$key]['highlighted'] = true; 2852db397b2SSatoshi Sahara $l_tags[$key]['highlighted'] = true; 2862db397b2SSatoshi Sahara } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { 2872db397b2SSatoshi Sahara unset($r_tags[$key]); 2882db397b2SSatoshi Sahara unset($l_tags[$key]); 2892db397b2SSatoshi Sahara } 2902db397b2SSatoshi Sahara } 2912db397b2SSatoshi Sahara 2922db397b2SSatoshi Sahara echo '<tr>'; 2932db397b2SSatoshi Sahara foreach (array($l_tags, $r_tags) as $tags) { 294675f74fbSSatoshi Sahara echo '<td>'; 2952db397b2SSatoshi Sahara 2962db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 2972db397b2SSatoshi Sahara foreach ($tags as $tag) { 2982db397b2SSatoshi Sahara $value = cleanText($tag['value']); 2992db397b2SSatoshi Sahara if (!$value) $value = '-'; 3002db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 3012db397b2SSatoshi Sahara echo '<dd>'; 3022db397b2SSatoshi Sahara if ($tag['highlighted']) echo '<strong>'; 3032db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 3042db397b2SSatoshi Sahara echo dformat($value); 3052db397b2SSatoshi Sahara } else { 3062db397b2SSatoshi Sahara echo hsc($value); 3072db397b2SSatoshi Sahara } 3082db397b2SSatoshi Sahara if ($tag['highlighted']) echo '</strong>'; 3092db397b2SSatoshi Sahara echo '</dd>'; 3102db397b2SSatoshi Sahara } 311675f74fbSSatoshi Sahara echo '</dl>'; 3122db397b2SSatoshi Sahara 3132db397b2SSatoshi Sahara echo '</td>'; 3142db397b2SSatoshi Sahara } 315675f74fbSSatoshi Sahara echo '</tr>'; 3162db397b2SSatoshi Sahara 317675f74fbSSatoshi Sahara echo '</table>'; 318675f74fbSSatoshi Sahara echo '</div>'; 31963ab9afeSSatoshi Sahara } 32063ab9afeSSatoshi Sahara 321179b4660SSatoshi Sahara /** 322179b4660SSatoshi Sahara * Revision Title for MediaDiff table headline 323179b4660SSatoshi Sahara * 324179b4660SSatoshi Sahara * @param array $info Revision info structure of a media file 325179b4660SSatoshi Sahara * @return string 326179b4660SSatoshi Sahara */ 327179b4660SSatoshi Sahara protected function revisionTitle(array $info) 328179b4660SSatoshi Sahara { 329a6dd7f90SSatoshi Sahara global $lang, $INFO; 330179b4660SSatoshi Sahara 331179b4660SSatoshi Sahara if (isset($info['date'])) { 332179b4660SSatoshi Sahara $rev = $info['date']; 333179b4660SSatoshi Sahara $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' 334179b4660SSatoshi Sahara . dformat($rev).'</a></bdi>'; 335179b4660SSatoshi Sahara } else { 336a6dd7f90SSatoshi Sahara $rev = false; 337179b4660SSatoshi Sahara $title = '—'; 338179b4660SSatoshi Sahara } 339179b4660SSatoshi Sahara if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { 340179b4660SSatoshi Sahara $title .= ' ('.$lang['current'].')'; 341179b4660SSatoshi Sahara } 342179b4660SSatoshi Sahara 343179b4660SSatoshi Sahara // append separator 344179b4660SSatoshi Sahara $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 345179b4660SSatoshi Sahara 346179b4660SSatoshi Sahara // supplement 347179b4660SSatoshi Sahara if (isset($info['date'])) { 348179b4660SSatoshi Sahara $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info); 349179b4660SSatoshi Sahara $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor(); 350179b4660SSatoshi Sahara } 351179b4660SSatoshi Sahara return $title; 352179b4660SSatoshi Sahara } 353179b4660SSatoshi Sahara 35463ab9afeSSatoshi Sahara} 355