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 210ea1f71bSSatoshi Sahara /* @var array */ 220ea1f71bSSatoshi Sahara protected $oldRevInfo; 230ea1f71bSSatoshi Sahara protected $newRevInfo; 240ea1f71bSSatoshi Sahara 250ea1f71bSSatoshi Sahara /* @var bool */ 260ea1f71bSSatoshi Sahara protected $is_img; 270ea1f71bSSatoshi 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; 420ea1f71bSSatoshi 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 530ea1f71bSSatoshi Sahara /** 540ea1f71bSSatoshi Sahara * Handle requested revision(s) and diff view preferences 550ea1f71bSSatoshi Sahara * 560ea1f71bSSatoshi Sahara * @return void 570ea1f71bSSatoshi Sahara */ 580ea1f71bSSatoshi Sahara protected function handle() 59b4b4c5c6SSatoshi Sahara { 600ea1f71bSSatoshi Sahara global $INPUT; 610ea1f71bSSatoshi Sahara 620ea1f71bSSatoshi Sahara // requested rev or rev2 630ea1f71bSSatoshi Sahara parent::handle(); 640ea1f71bSSatoshi Sahara 650ea1f71bSSatoshi Sahara // requested diff view type 660ea1f71bSSatoshi Sahara if ($INPUT->has('difftype')) { 670ea1f71bSSatoshi Sahara $this->preference['difftype'] = $INPUT->str('difftype'); 680ea1f71bSSatoshi Sahara } 690ea1f71bSSatoshi 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 /** 790ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 800ea1f71bSSatoshi Sahara */ 810ea1f71bSSatoshi Sahara protected function preProcess() 820ea1f71bSSatoshi Sahara { 830ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 840ea1f71bSSatoshi Sahara 850ea1f71bSSatoshi Sahara // revision info of older file (left side) 860ea1f71bSSatoshi Sahara $this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev); 870ea1f71bSSatoshi Sahara // revision info of newer file (right side) 880ea1f71bSSatoshi Sahara $this->newRevInfo = $changelog->getRevisionInfo($this->newRev); 890ea1f71bSSatoshi Sahara 900ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 910ea1f71bSSatoshi Sahara 920ea1f71bSSatoshi Sahara foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { 930ea1f71bSSatoshi Sahara // use timestamp and '' properly as $rev for the current file 94*5ec96136SSatoshi Sahara $isCurrent = $changelog->isCurrentRevision($revInfo['date']); 95*5ec96136SSatoshi Sahara $revInfo += [ 96*5ec96136SSatoshi Sahara 'current' => $isCurrent, 97*5ec96136SSatoshi Sahara 'rev' => $isCurrent ? '' : $revInfo['date'], 98*5ec96136SSatoshi Sahara ]; 990ea1f71bSSatoshi Sahara 1000ea1f71bSSatoshi Sahara // headline in the Diff view navigation 1010ea1f71bSSatoshi Sahara $revInfo['navTitle'] = $this->revisionTitle($revInfo); 1020ea1f71bSSatoshi Sahara 1030ea1f71bSSatoshi Sahara if ($this->is_img) { 104*5ec96136SSatoshi Sahara $rev = $revInfo['rev']; 1050ea1f71bSSatoshi Sahara $meta = new JpegMeta(mediaFN($this->id, $rev)); 1060ea1f71bSSatoshi Sahara // get image width and height for the mediamanager preview panel 1070ea1f71bSSatoshi Sahara $revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta); 1080ea1f71bSSatoshi Sahara } 1090ea1f71bSSatoshi Sahara } 1100ea1f71bSSatoshi Sahara unset($revInfo); 1110ea1f71bSSatoshi Sahara 1120ea1f71bSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 1130ea1f71bSSatoshi Sahara $this->is_img = ($this->is_img 1140ea1f71bSSatoshi Sahara && ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30 1150ea1f71bSSatoshi Sahara && ($this->newRevInfo['previewSize'][0] ?? 0) >= 30 1160ea1f71bSSatoshi Sahara ); 1170ea1f71bSSatoshi Sahara // adjust requested diff view type 1180ea1f71bSSatoshi Sahara if (!$this->is_img) { 1190ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; 1200ea1f71bSSatoshi Sahara } 1210ea1f71bSSatoshi Sahara } 1220ea1f71bSSatoshi Sahara 1230ea1f71bSSatoshi Sahara 1240ea1f71bSSatoshi Sahara /** 12563ab9afeSSatoshi Sahara * Shows difference between two revisions of media 126675f74fbSSatoshi Sahara * 127675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 12863ab9afeSSatoshi Sahara */ 129309aaee5SSatoshi Sahara public function show() 13063ab9afeSSatoshi Sahara { 131675f74fbSSatoshi Sahara global $conf; 132675f74fbSSatoshi Sahara 13363ab9afeSSatoshi Sahara $ns = getNS($this->id); 13463ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 135675f74fbSSatoshi Sahara 136675f74fbSSatoshi Sahara if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return ''; 137675f74fbSSatoshi Sahara 1380ea1f71bSSatoshi Sahara // retrieve form parameters: rev, rev2, difftype 1390ea1f71bSSatoshi Sahara $this->handle(); 1400ea1f71bSSatoshi Sahara // prepare revision info of comparison pair 1410ea1f71bSSatoshi Sahara $this->preProcess(); 142675f74fbSSatoshi Sahara 143675f74fbSSatoshi Sahara // display intro 144675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 145675f74fbSSatoshi Sahara 146675f74fbSSatoshi Sahara // print form to choose diff view type 1470ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 14891e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 149675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 150675f74fbSSatoshi Sahara } 151675f74fbSSatoshi Sahara 152309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 153675f74fbSSatoshi Sahara case 'opacity': 154675f74fbSSatoshi Sahara case 'portions': 1550ea1f71bSSatoshi Sahara $this->showImageDiff(); 156675f74fbSSatoshi Sahara break; 157675f74fbSSatoshi Sahara case 'both': 158675f74fbSSatoshi Sahara default: 1590ea1f71bSSatoshi Sahara $this->showFileDiff(); 160675f74fbSSatoshi Sahara break; 161675f74fbSSatoshi Sahara } 162675f74fbSSatoshi Sahara 1630ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 164675f74fbSSatoshi Sahara echo '</div>'; 165675f74fbSSatoshi Sahara } 1662db397b2SSatoshi Sahara } 1672db397b2SSatoshi Sahara 1682db397b2SSatoshi Sahara /** 169675f74fbSSatoshi Sahara * Print form to choose diff view type 170675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1712db397b2SSatoshi Sahara */ 17291e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1732db397b2SSatoshi Sahara { 1740ea1f71bSSatoshi Sahara // use timestamp for current revision 1750ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; 1760ea1f71bSSatoshi Sahara 17791e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 17891e70b5fSSatoshi Sahara 1792db397b2SSatoshi Sahara $form = new Form([ 1802db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1812db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1822db397b2SSatoshi Sahara 'method' => 'get', 1832db397b2SSatoshi Sahara 'class' => 'diffView', 1842db397b2SSatoshi Sahara ]); 1852db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1862db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1872db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 1880ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[0]', $oldRev); 1890ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[1]', $newRev); 1902db397b2SSatoshi Sahara $form->addTagClose('div'); 1912db397b2SSatoshi Sahara echo $form->toHTML(); 19291e70b5fSSatoshi Sahara 19391e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1942db397b2SSatoshi Sahara } 1952db397b2SSatoshi Sahara 196675f74fbSSatoshi Sahara /** 197675f74fbSSatoshi Sahara * Prints two images side by side 198675f74fbSSatoshi Sahara * and slider 199675f74fbSSatoshi Sahara * 200675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 201675f74fbSSatoshi Sahara */ 2020ea1f71bSSatoshi Sahara protected function showImageDiff() 203675f74fbSSatoshi Sahara { 2040ea1f71bSSatoshi Sahara // diff view type: opacity or portions 205675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 2060ea1f71bSSatoshi Sahara 2070ea1f71bSSatoshi Sahara // use '' for current revision 2080ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 209675f74fbSSatoshi Sahara 210675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 2110ea1f71bSSatoshi Sahara $oldRevSize = $this->oldRevInfo['previewSize']; 2120ea1f71bSSatoshi Sahara $newRevSize = $this->newRevInfo['previewSize']; 2133d0f231eSSatoshi Sahara if ($oldRevSize != $newRevSize) { 2143d0f231eSSatoshi Sahara if ($newRevSize[0] > $oldRevSize[0]) { 2153d0f231eSSatoshi Sahara $oldRevSize = $newRevSize; 2162db397b2SSatoshi Sahara } 2172db397b2SSatoshi Sahara } 2182db397b2SSatoshi Sahara 2193d0f231eSSatoshi Sahara $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 2203d0f231eSSatoshi Sahara $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 221675f74fbSSatoshi Sahara 222675f74fbSSatoshi Sahara // slider 2233d0f231eSSatoshi Sahara echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; 224675f74fbSSatoshi Sahara 225675f74fbSSatoshi Sahara // two images in divs 226675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2273d0f231eSSatoshi Sahara echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; 2283d0f231eSSatoshi Sahara echo '<img src="'.$oldRevSrc.'" alt="" />'; 229675f74fbSSatoshi Sahara echo '</div>'; 2303d0f231eSSatoshi Sahara echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; 2313d0f231eSSatoshi Sahara echo '<img src="'.$newRevSrc.'" alt="" />'; 232675f74fbSSatoshi Sahara echo '</div>'; 233675f74fbSSatoshi Sahara echo '</div>'; 234675f74fbSSatoshi Sahara } 235675f74fbSSatoshi Sahara 236675f74fbSSatoshi Sahara /** 237675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 238675f74fbSSatoshi Sahara * 239675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 240675f74fbSSatoshi Sahara */ 2410ea1f71bSSatoshi Sahara protected function showFileDiff() 242675f74fbSSatoshi Sahara { 243a6dd7f90SSatoshi Sahara global $lang; 24464876922SSatoshi Sahara $changelog =& $this->changelog; 245a6dd7f90SSatoshi Sahara 2460ea1f71bSSatoshi Sahara $ns = getNS($this->id); 2470ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 2480ea1f71bSSatoshi Sahara 2490ea1f71bSSatoshi Sahara // use '' for current revision 2500ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 2510ea1f71bSSatoshi Sahara 2520ea1f71bSSatoshi Sahara $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); 2530ea1f71bSSatoshi Sahara $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); 2542db397b2SSatoshi Sahara 255179b4660SSatoshi Sahara // display diff view table 2562db397b2SSatoshi Sahara echo '<div class="table">'; 2572db397b2SSatoshi Sahara echo '<table>'; 2582db397b2SSatoshi Sahara echo '<tr>'; 2590ea1f71bSSatoshi Sahara echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>'; 2600ea1f71bSSatoshi Sahara echo '<th>'. $this->newRevInfo['navTitle'] .'</th>'; 261675f74fbSSatoshi Sahara echo '</tr>'; 2622db397b2SSatoshi Sahara 2632db397b2SSatoshi Sahara echo '<tr class="image">'; 2642db397b2SSatoshi Sahara echo '<td>'; 2653d0f231eSSatoshi Sahara media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? 2662db397b2SSatoshi Sahara echo '</td>'; 2672db397b2SSatoshi Sahara 2682db397b2SSatoshi Sahara echo '<td>'; 2693d0f231eSSatoshi Sahara media_preview($this->id, $auth, $newRev, $newRevMeta); 2702db397b2SSatoshi Sahara echo '</td>'; 271675f74fbSSatoshi Sahara echo '</tr>'; 2722db397b2SSatoshi Sahara 2732db397b2SSatoshi Sahara echo '<tr class="actions">'; 2742db397b2SSatoshi Sahara echo '<td>'; 2753d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() 2762db397b2SSatoshi Sahara echo '</td>'; 2772db397b2SSatoshi Sahara 2782db397b2SSatoshi Sahara echo '<td>'; 2793d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $newRev); 2802db397b2SSatoshi Sahara echo '</td>'; 281675f74fbSSatoshi Sahara echo '</tr>'; 2822db397b2SSatoshi Sahara 2833d0f231eSSatoshi Sahara $l_tags = media_file_tags($oldRevMeta); 2843d0f231eSSatoshi Sahara $r_tags = media_file_tags($newRevMeta); 2852db397b2SSatoshi Sahara // FIXME r_tags-only stuff 2862db397b2SSatoshi Sahara foreach ($l_tags as $key => $l_tag) { 2872db397b2SSatoshi Sahara if ($l_tag['value'] != $r_tags[$key]['value']) { 2882db397b2SSatoshi Sahara $r_tags[$key]['highlighted'] = true; 2892db397b2SSatoshi Sahara $l_tags[$key]['highlighted'] = true; 2902db397b2SSatoshi Sahara } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { 2912db397b2SSatoshi Sahara unset($r_tags[$key]); 2922db397b2SSatoshi Sahara unset($l_tags[$key]); 2932db397b2SSatoshi Sahara } 2942db397b2SSatoshi Sahara } 2952db397b2SSatoshi Sahara 2962db397b2SSatoshi Sahara echo '<tr>'; 2972db397b2SSatoshi Sahara foreach (array($l_tags, $r_tags) as $tags) { 298675f74fbSSatoshi Sahara echo '<td>'; 2992db397b2SSatoshi Sahara 3002db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 3012db397b2SSatoshi Sahara foreach ($tags as $tag) { 3022db397b2SSatoshi Sahara $value = cleanText($tag['value']); 3032db397b2SSatoshi Sahara if (!$value) $value = '-'; 3042db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 3052db397b2SSatoshi Sahara echo '<dd>'; 3062db397b2SSatoshi Sahara if ($tag['highlighted']) echo '<strong>'; 3072db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 3082db397b2SSatoshi Sahara echo dformat($value); 3092db397b2SSatoshi Sahara } else { 3102db397b2SSatoshi Sahara echo hsc($value); 3112db397b2SSatoshi Sahara } 3122db397b2SSatoshi Sahara if ($tag['highlighted']) echo '</strong>'; 3132db397b2SSatoshi Sahara echo '</dd>'; 3142db397b2SSatoshi Sahara } 315675f74fbSSatoshi Sahara echo '</dl>'; 3162db397b2SSatoshi Sahara 3172db397b2SSatoshi Sahara echo '</td>'; 3182db397b2SSatoshi Sahara } 319675f74fbSSatoshi Sahara echo '</tr>'; 3202db397b2SSatoshi Sahara 321675f74fbSSatoshi Sahara echo '</table>'; 322675f74fbSSatoshi Sahara echo '</div>'; 32363ab9afeSSatoshi Sahara } 32463ab9afeSSatoshi Sahara 325179b4660SSatoshi Sahara /** 326179b4660SSatoshi Sahara * Revision Title for MediaDiff table headline 327179b4660SSatoshi Sahara * 328179b4660SSatoshi Sahara * @param array $info Revision info structure of a media file 329179b4660SSatoshi Sahara * @return string 330179b4660SSatoshi Sahara */ 331179b4660SSatoshi Sahara protected function revisionTitle(array $info) 332179b4660SSatoshi Sahara { 333a6dd7f90SSatoshi Sahara global $lang, $INFO; 334179b4660SSatoshi Sahara 335179b4660SSatoshi Sahara if (isset($info['date'])) { 336179b4660SSatoshi Sahara $rev = $info['date']; 337179b4660SSatoshi Sahara $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' 338179b4660SSatoshi Sahara . dformat($rev).'</a></bdi>'; 339179b4660SSatoshi Sahara } else { 340a6dd7f90SSatoshi Sahara $rev = false; 341179b4660SSatoshi Sahara $title = '—'; 342179b4660SSatoshi Sahara } 343179b4660SSatoshi Sahara if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { 344179b4660SSatoshi Sahara $title .= ' ('.$lang['current'].')'; 345179b4660SSatoshi Sahara } 346179b4660SSatoshi Sahara 347179b4660SSatoshi Sahara // append separator 348179b4660SSatoshi Sahara $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 349179b4660SSatoshi Sahara 350179b4660SSatoshi Sahara // supplement 351179b4660SSatoshi Sahara if (isset($info['date'])) { 352179b4660SSatoshi Sahara $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info); 353179b4660SSatoshi Sahara $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor(); 354179b4660SSatoshi Sahara } 355179b4660SSatoshi Sahara return $title; 356179b4660SSatoshi Sahara } 357179b4660SSatoshi Sahara 35863ab9afeSSatoshi Sahara} 359