163ab9afeSSatoshi Sahara<?php 263ab9afeSSatoshi Sahara 363ab9afeSSatoshi Saharanamespace dokuwiki\Ui; 463ab9afeSSatoshi Sahara 563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog; 663ab9afeSSatoshi Saharause dokuwiki\Form\Form; 7*79a2d784SGerrit Uitslaguse InvalidArgumentException; 830a159abSSatoshi Saharause JpegMeta; 963ab9afeSSatoshi Sahara 1063ab9afeSSatoshi Sahara/** 1163ab9afeSSatoshi Sahara * DokuWiki MediaDiff Interface 1263ab9afeSSatoshi Sahara * 1363ab9afeSSatoshi Sahara * @package dokuwiki\Ui 1463ab9afeSSatoshi Sahara */ 1563ab9afeSSatoshi Saharaclass MediaDiff extends Diff 1663ab9afeSSatoshi Sahara{ 17d9c75b22SSatoshi Sahara /* @var MediaChangeLog */ 18d9c75b22SSatoshi Sahara protected $changelog; 19d9c75b22SSatoshi Sahara 200ea1f71bSSatoshi Sahara /* @var array */ 210ea1f71bSSatoshi Sahara protected $oldRevInfo; 220ea1f71bSSatoshi Sahara protected $newRevInfo; 230ea1f71bSSatoshi Sahara 240ea1f71bSSatoshi Sahara /* @var bool */ 250ea1f71bSSatoshi Sahara protected $is_img; 260ea1f71bSSatoshi Sahara 2763ab9afeSSatoshi Sahara /** 2863ab9afeSSatoshi Sahara * MediaDiff Ui constructor 2963ab9afeSSatoshi Sahara * 30edb50e6aSSatoshi Sahara * @param string $id media id 3163ab9afeSSatoshi Sahara */ 32edb50e6aSSatoshi Sahara public function __construct($id) 3363ab9afeSSatoshi Sahara { 344557f463SSatoshi Sahara if (!isset($id)) { 35*79a2d784SGerrit Uitslag throw new InvalidArgumentException('media id should not be empty!'); 3630a159abSSatoshi Sahara } 37edb50e6aSSatoshi Sahara 38295564cdSSatoshi Sahara // init preference 396527839fSSatoshi Sahara $this->preference['fromAjax'] = false; // see dokuwiki\Ajax::callMediadiff() 40edb50e6aSSatoshi Sahara $this->preference['showIntro'] = false; 410ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions 428068440fSSatoshi Sahara 4330a159abSSatoshi Sahara parent::__construct($id); 448068440fSSatoshi Sahara } 458068440fSSatoshi Sahara 468068440fSSatoshi Sahara /** @inheritdoc */ 478068440fSSatoshi Sahara protected function setChangeLog() 488068440fSSatoshi Sahara { 498068440fSSatoshi Sahara $this->changelog = new MediaChangeLog($this->id); 5063ab9afeSSatoshi Sahara } 5163ab9afeSSatoshi Sahara 520ea1f71bSSatoshi Sahara /** 530ea1f71bSSatoshi Sahara * Handle requested revision(s) and diff view preferences 540ea1f71bSSatoshi Sahara * 550ea1f71bSSatoshi Sahara * @return void 560ea1f71bSSatoshi Sahara */ 570ea1f71bSSatoshi Sahara protected function handle() 58b4b4c5c6SSatoshi Sahara { 590ea1f71bSSatoshi Sahara global $INPUT; 600ea1f71bSSatoshi Sahara 610ea1f71bSSatoshi Sahara // requested rev or rev2 620ea1f71bSSatoshi Sahara parent::handle(); 630ea1f71bSSatoshi Sahara 640ea1f71bSSatoshi Sahara // requested diff view type 650ea1f71bSSatoshi Sahara if ($INPUT->has('difftype')) { 660ea1f71bSSatoshi Sahara $this->preference['difftype'] = $INPUT->str('difftype'); 670ea1f71bSSatoshi Sahara } 68b4b4c5c6SSatoshi Sahara } 69b4b4c5c6SSatoshi Sahara 7063ab9afeSSatoshi Sahara /** 710ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 720ea1f71bSSatoshi Sahara */ 730ea1f71bSSatoshi Sahara protected function preProcess() 740ea1f71bSSatoshi Sahara { 750ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 760ea1f71bSSatoshi Sahara 770ea1f71bSSatoshi Sahara // revision info of older file (left side) 780ea1f71bSSatoshi Sahara $this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev); 790ea1f71bSSatoshi Sahara // revision info of newer file (right side) 800ea1f71bSSatoshi Sahara $this->newRevInfo = $changelog->getRevisionInfo($this->newRev); 810ea1f71bSSatoshi Sahara 820ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 830ea1f71bSSatoshi Sahara 840ea1f71bSSatoshi Sahara foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { 850ea1f71bSSatoshi Sahara // use timestamp and '' properly as $rev for the current file 865ec96136SSatoshi Sahara $isCurrent = $changelog->isCurrentRevision($revInfo['date']); 875ec96136SSatoshi Sahara $revInfo += [ 885ec96136SSatoshi Sahara 'current' => $isCurrent, 895ec96136SSatoshi Sahara 'rev' => $isCurrent ? '' : $revInfo['date'], 905ec96136SSatoshi Sahara ]; 910ea1f71bSSatoshi Sahara 920ea1f71bSSatoshi Sahara // headline in the Diff view navigation 930ea1f71bSSatoshi Sahara $revInfo['navTitle'] = $this->revisionTitle($revInfo); 940ea1f71bSSatoshi Sahara 950ea1f71bSSatoshi Sahara if ($this->is_img) { 965ec96136SSatoshi Sahara $rev = $revInfo['rev']; 970ea1f71bSSatoshi Sahara $meta = new JpegMeta(mediaFN($this->id, $rev)); 980ea1f71bSSatoshi Sahara // get image width and height for the mediamanager preview panel 990ea1f71bSSatoshi Sahara $revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta); 1000ea1f71bSSatoshi Sahara } 1010ea1f71bSSatoshi Sahara } 1020ea1f71bSSatoshi Sahara unset($revInfo); 1030ea1f71bSSatoshi Sahara 1040ea1f71bSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 1050ea1f71bSSatoshi Sahara $this->is_img = ($this->is_img 1060ea1f71bSSatoshi Sahara && ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30 1070ea1f71bSSatoshi Sahara && ($this->newRevInfo['previewSize'][0] ?? 0) >= 30 1080ea1f71bSSatoshi Sahara ); 1090ea1f71bSSatoshi Sahara // adjust requested diff view type 1100ea1f71bSSatoshi Sahara if (!$this->is_img) { 1110ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; 1120ea1f71bSSatoshi Sahara } 1130ea1f71bSSatoshi Sahara } 1140ea1f71bSSatoshi Sahara 1150ea1f71bSSatoshi Sahara 1160ea1f71bSSatoshi Sahara /** 11763ab9afeSSatoshi Sahara * Shows difference between two revisions of media 118675f74fbSSatoshi Sahara * 119675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 12063ab9afeSSatoshi Sahara */ 121309aaee5SSatoshi Sahara public function show() 12263ab9afeSSatoshi Sahara { 123675f74fbSSatoshi Sahara global $conf; 124675f74fbSSatoshi Sahara 12563ab9afeSSatoshi Sahara $ns = getNS($this->id); 12663ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 127675f74fbSSatoshi Sahara 128*79a2d784SGerrit Uitslag if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return; 129675f74fbSSatoshi Sahara 1300ea1f71bSSatoshi Sahara // retrieve form parameters: rev, rev2, difftype 1310ea1f71bSSatoshi Sahara $this->handle(); 1320ea1f71bSSatoshi Sahara // prepare revision info of comparison pair 1330ea1f71bSSatoshi Sahara $this->preProcess(); 134675f74fbSSatoshi Sahara 135675f74fbSSatoshi Sahara // display intro 136675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 137675f74fbSSatoshi Sahara 138675f74fbSSatoshi Sahara // print form to choose diff view type 1390ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 14091e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 141675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 142675f74fbSSatoshi Sahara } 143675f74fbSSatoshi Sahara 144309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 145675f74fbSSatoshi Sahara case 'opacity': 146675f74fbSSatoshi Sahara case 'portions': 1470ea1f71bSSatoshi Sahara $this->showImageDiff(); 148675f74fbSSatoshi Sahara break; 149675f74fbSSatoshi Sahara case 'both': 150675f74fbSSatoshi Sahara default: 1510ea1f71bSSatoshi Sahara $this->showFileDiff(); 152675f74fbSSatoshi Sahara break; 153675f74fbSSatoshi Sahara } 154675f74fbSSatoshi Sahara 1550ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 156675f74fbSSatoshi Sahara echo '</div>'; 157675f74fbSSatoshi Sahara } 1582db397b2SSatoshi Sahara } 1592db397b2SSatoshi Sahara 1602db397b2SSatoshi Sahara /** 161675f74fbSSatoshi Sahara * Print form to choose diff view type 162675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1632db397b2SSatoshi Sahara */ 16491e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1652db397b2SSatoshi Sahara { 1660ea1f71bSSatoshi Sahara // use timestamp for current revision 1670ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; 1680ea1f71bSSatoshi Sahara 16991e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 17091e70b5fSSatoshi Sahara 1712db397b2SSatoshi Sahara $form = new Form([ 1722db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1732db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1742db397b2SSatoshi Sahara 'method' => 'get', 1752db397b2SSatoshi Sahara 'class' => 'diffView', 1762db397b2SSatoshi Sahara ]); 1772db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1782db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1792db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 1800ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[0]', $oldRev); 1810ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[1]', $newRev); 1822db397b2SSatoshi Sahara $form->addTagClose('div'); 1832db397b2SSatoshi Sahara echo $form->toHTML(); 18491e70b5fSSatoshi Sahara 18591e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1862db397b2SSatoshi Sahara } 1872db397b2SSatoshi Sahara 188675f74fbSSatoshi Sahara /** 189675f74fbSSatoshi Sahara * Prints two images side by side 190675f74fbSSatoshi Sahara * and slider 191675f74fbSSatoshi Sahara * 192675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 193675f74fbSSatoshi Sahara */ 1940ea1f71bSSatoshi Sahara protected function showImageDiff() 195675f74fbSSatoshi Sahara { 1960ea1f71bSSatoshi Sahara // diff view type: opacity or portions 197675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 1980ea1f71bSSatoshi Sahara 1990ea1f71bSSatoshi Sahara // use '' for current revision 2000ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 201675f74fbSSatoshi Sahara 202675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 2030ea1f71bSSatoshi Sahara $oldRevSize = $this->oldRevInfo['previewSize']; 2040ea1f71bSSatoshi Sahara $newRevSize = $this->newRevInfo['previewSize']; 2053d0f231eSSatoshi Sahara if ($oldRevSize != $newRevSize) { 2063d0f231eSSatoshi Sahara if ($newRevSize[0] > $oldRevSize[0]) { 2073d0f231eSSatoshi Sahara $oldRevSize = $newRevSize; 2082db397b2SSatoshi Sahara } 2092db397b2SSatoshi Sahara } 2102db397b2SSatoshi Sahara 2113d0f231eSSatoshi Sahara $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 2123d0f231eSSatoshi Sahara $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 213675f74fbSSatoshi Sahara 214675f74fbSSatoshi Sahara // slider 2153d0f231eSSatoshi Sahara echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; 216675f74fbSSatoshi Sahara 217675f74fbSSatoshi Sahara // two images in divs 218675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2193d0f231eSSatoshi Sahara echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; 2203d0f231eSSatoshi Sahara echo '<img src="'.$oldRevSrc.'" alt="" />'; 221675f74fbSSatoshi Sahara echo '</div>'; 2223d0f231eSSatoshi Sahara echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; 2233d0f231eSSatoshi Sahara echo '<img src="'.$newRevSrc.'" alt="" />'; 224675f74fbSSatoshi Sahara echo '</div>'; 225675f74fbSSatoshi Sahara echo '</div>'; 226675f74fbSSatoshi Sahara } 227675f74fbSSatoshi Sahara 228675f74fbSSatoshi Sahara /** 229675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 230675f74fbSSatoshi Sahara * 231675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 232675f74fbSSatoshi Sahara */ 2330ea1f71bSSatoshi Sahara protected function showFileDiff() 234675f74fbSSatoshi Sahara { 235a6dd7f90SSatoshi Sahara global $lang; 236a6dd7f90SSatoshi Sahara 2370ea1f71bSSatoshi Sahara $ns = getNS($this->id); 2380ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 2390ea1f71bSSatoshi Sahara 2400ea1f71bSSatoshi Sahara // use '' for current revision 2410ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 2420ea1f71bSSatoshi Sahara 2430ea1f71bSSatoshi Sahara $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); 2440ea1f71bSSatoshi Sahara $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); 2452db397b2SSatoshi Sahara 246179b4660SSatoshi Sahara // display diff view table 2472db397b2SSatoshi Sahara echo '<div class="table">'; 2482db397b2SSatoshi Sahara echo '<table>'; 2492db397b2SSatoshi Sahara echo '<tr>'; 2500ea1f71bSSatoshi Sahara echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>'; 2510ea1f71bSSatoshi Sahara echo '<th>'. $this->newRevInfo['navTitle'] .'</th>'; 252675f74fbSSatoshi Sahara echo '</tr>'; 2532db397b2SSatoshi Sahara 2542db397b2SSatoshi Sahara echo '<tr class="image">'; 2552db397b2SSatoshi Sahara echo '<td>'; 2563d0f231eSSatoshi Sahara media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? 2572db397b2SSatoshi Sahara echo '</td>'; 2582db397b2SSatoshi Sahara 2592db397b2SSatoshi Sahara echo '<td>'; 2603d0f231eSSatoshi Sahara media_preview($this->id, $auth, $newRev, $newRevMeta); 2612db397b2SSatoshi Sahara echo '</td>'; 262675f74fbSSatoshi Sahara echo '</tr>'; 2632db397b2SSatoshi Sahara 2642db397b2SSatoshi Sahara echo '<tr class="actions">'; 2652db397b2SSatoshi Sahara echo '<td>'; 2663d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() 2672db397b2SSatoshi Sahara echo '</td>'; 2682db397b2SSatoshi Sahara 2692db397b2SSatoshi Sahara echo '<td>'; 2703d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $newRev); 2712db397b2SSatoshi Sahara echo '</td>'; 272675f74fbSSatoshi Sahara echo '</tr>'; 2732db397b2SSatoshi Sahara 2743d0f231eSSatoshi Sahara $l_tags = media_file_tags($oldRevMeta); 2753d0f231eSSatoshi Sahara $r_tags = media_file_tags($newRevMeta); 2762db397b2SSatoshi Sahara // FIXME r_tags-only stuff 2772db397b2SSatoshi Sahara foreach ($l_tags as $key => $l_tag) { 2782db397b2SSatoshi Sahara if ($l_tag['value'] != $r_tags[$key]['value']) { 2792db397b2SSatoshi Sahara $r_tags[$key]['highlighted'] = true; 2802db397b2SSatoshi Sahara $l_tags[$key]['highlighted'] = true; 2812db397b2SSatoshi Sahara } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { 2822db397b2SSatoshi Sahara unset($r_tags[$key]); 2832db397b2SSatoshi Sahara unset($l_tags[$key]); 2842db397b2SSatoshi Sahara } 2852db397b2SSatoshi Sahara } 2862db397b2SSatoshi Sahara 2872db397b2SSatoshi Sahara echo '<tr>'; 2882db397b2SSatoshi Sahara foreach (array($l_tags, $r_tags) as $tags) { 289675f74fbSSatoshi Sahara echo '<td>'; 2902db397b2SSatoshi Sahara 2912db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 2922db397b2SSatoshi Sahara foreach ($tags as $tag) { 2932db397b2SSatoshi Sahara $value = cleanText($tag['value']); 2942db397b2SSatoshi Sahara if (!$value) $value = '-'; 2952db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 2962db397b2SSatoshi Sahara echo '<dd>'; 2972db397b2SSatoshi Sahara if ($tag['highlighted']) echo '<strong>'; 2982db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 2992db397b2SSatoshi Sahara echo dformat($value); 3002db397b2SSatoshi Sahara } else { 3012db397b2SSatoshi Sahara echo hsc($value); 3022db397b2SSatoshi Sahara } 3032db397b2SSatoshi Sahara if ($tag['highlighted']) echo '</strong>'; 3042db397b2SSatoshi Sahara echo '</dd>'; 3052db397b2SSatoshi Sahara } 306675f74fbSSatoshi Sahara echo '</dl>'; 3072db397b2SSatoshi Sahara 3082db397b2SSatoshi Sahara echo '</td>'; 3092db397b2SSatoshi Sahara } 310675f74fbSSatoshi Sahara echo '</tr>'; 3112db397b2SSatoshi Sahara 312675f74fbSSatoshi Sahara echo '</table>'; 313675f74fbSSatoshi Sahara echo '</div>'; 31463ab9afeSSatoshi Sahara } 31563ab9afeSSatoshi Sahara 316179b4660SSatoshi Sahara /** 317179b4660SSatoshi Sahara * Revision Title for MediaDiff table headline 318179b4660SSatoshi Sahara * 319179b4660SSatoshi Sahara * @param array $info Revision info structure of a media file 320179b4660SSatoshi Sahara * @return string 321179b4660SSatoshi Sahara */ 322179b4660SSatoshi Sahara protected function revisionTitle(array $info) 323179b4660SSatoshi Sahara { 324a6dd7f90SSatoshi Sahara global $lang, $INFO; 325179b4660SSatoshi Sahara 326179b4660SSatoshi Sahara if (isset($info['date'])) { 327179b4660SSatoshi Sahara $rev = $info['date']; 328179b4660SSatoshi Sahara $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' 329179b4660SSatoshi Sahara . dformat($rev).'</a></bdi>'; 330179b4660SSatoshi Sahara } else { 331a6dd7f90SSatoshi Sahara $rev = false; 332179b4660SSatoshi Sahara $title = '—'; 333179b4660SSatoshi Sahara } 334179b4660SSatoshi Sahara if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { 335179b4660SSatoshi Sahara $title .= ' ('.$lang['current'].')'; 336179b4660SSatoshi Sahara } 337179b4660SSatoshi Sahara 338179b4660SSatoshi Sahara // append separator 339179b4660SSatoshi Sahara $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 340179b4660SSatoshi Sahara 341179b4660SSatoshi Sahara // supplement 342179b4660SSatoshi Sahara if (isset($info['date'])) { 343179b4660SSatoshi Sahara $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info); 344179b4660SSatoshi Sahara $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor(); 345179b4660SSatoshi Sahara } 346179b4660SSatoshi Sahara return $title; 347179b4660SSatoshi Sahara } 348179b4660SSatoshi Sahara 34963ab9afeSSatoshi Sahara} 350