163ab9afeSSatoshi Sahara<?php 263ab9afeSSatoshi Sahara 363ab9afeSSatoshi Saharanamespace dokuwiki\Ui; 463ab9afeSSatoshi Sahara 563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog; 6bf3fa5e9SSatoshi Saharause dokuwiki\ChangeLog\RevisionInfo; 763ab9afeSSatoshi Saharause dokuwiki\Form\Form; 879a2d784SGerrit Uitslaguse InvalidArgumentException; 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)) { 3679a2d784SGerrit Uitslag throw new InvalidArgumentException('media id should not be empty!'); 3730a159abSSatoshi Sahara } 38edb50e6aSSatoshi Sahara 39295564cdSSatoshi Sahara // init preference 406527839fSSatoshi Sahara $this->preference['fromAjax'] = false; // see dokuwiki\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 } 69b4b4c5c6SSatoshi Sahara } 70b4b4c5c6SSatoshi Sahara 7163ab9afeSSatoshi Sahara /** 720ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 730ea1f71bSSatoshi Sahara */ 740ea1f71bSSatoshi Sahara protected function preProcess() 750ea1f71bSSatoshi Sahara { 760ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 770ea1f71bSSatoshi Sahara 780ea1f71bSSatoshi Sahara // revision info of older file (left side) 790ea1f71bSSatoshi Sahara $this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev); 800ea1f71bSSatoshi Sahara // revision info of newer file (right side) 810ea1f71bSSatoshi Sahara $this->newRevInfo = $changelog->getRevisionInfo($this->newRev); 820ea1f71bSSatoshi Sahara 830ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 840ea1f71bSSatoshi Sahara 850ea1f71bSSatoshi Sahara foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) { 860ea1f71bSSatoshi Sahara // use timestamp and '' properly as $rev for the current file 875ec96136SSatoshi Sahara $isCurrent = $changelog->isCurrentRevision($revInfo['date']); 885ec96136SSatoshi Sahara $revInfo += [ 895ec96136SSatoshi Sahara 'current' => $isCurrent, 905ec96136SSatoshi Sahara 'rev' => $isCurrent ? '' : $revInfo['date'], 915ec96136SSatoshi Sahara ]; 920ea1f71bSSatoshi Sahara 930ea1f71bSSatoshi Sahara // headline in the Diff view navigation 940ea1f71bSSatoshi Sahara $revInfo['navTitle'] = $this->revisionTitle($revInfo); 950ea1f71bSSatoshi Sahara 960ea1f71bSSatoshi Sahara if ($this->is_img) { 975ec96136SSatoshi Sahara $rev = $revInfo['rev']; 980ea1f71bSSatoshi Sahara $meta = new JpegMeta(mediaFN($this->id, $rev)); 990ea1f71bSSatoshi Sahara // get image width and height for the mediamanager preview panel 1000ea1f71bSSatoshi Sahara $revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta); 1010ea1f71bSSatoshi Sahara } 1020ea1f71bSSatoshi Sahara } 1030ea1f71bSSatoshi Sahara unset($revInfo); 1040ea1f71bSSatoshi Sahara 1050ea1f71bSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 1060ea1f71bSSatoshi Sahara $this->is_img = ($this->is_img 1070ea1f71bSSatoshi Sahara && ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30 1080ea1f71bSSatoshi Sahara && ($this->newRevInfo['previewSize'][0] ?? 0) >= 30 1090ea1f71bSSatoshi Sahara ); 1100ea1f71bSSatoshi Sahara // adjust requested diff view type 1110ea1f71bSSatoshi Sahara if (!$this->is_img) { 1120ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; 1130ea1f71bSSatoshi Sahara } 1140ea1f71bSSatoshi Sahara } 1150ea1f71bSSatoshi Sahara 1160ea1f71bSSatoshi Sahara 1170ea1f71bSSatoshi Sahara /** 11863ab9afeSSatoshi Sahara * Shows difference between two revisions of media 119675f74fbSSatoshi Sahara * 120675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 12163ab9afeSSatoshi Sahara */ 122309aaee5SSatoshi Sahara public function show() 12363ab9afeSSatoshi Sahara { 124675f74fbSSatoshi Sahara global $conf; 125675f74fbSSatoshi Sahara 12663ab9afeSSatoshi Sahara $ns = getNS($this->id); 12763ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 128675f74fbSSatoshi Sahara 12979a2d784SGerrit Uitslag if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return; 130675f74fbSSatoshi Sahara 1310ea1f71bSSatoshi Sahara // retrieve form parameters: rev, rev2, difftype 1320ea1f71bSSatoshi Sahara $this->handle(); 1330ea1f71bSSatoshi Sahara // prepare revision info of comparison pair 1340ea1f71bSSatoshi Sahara $this->preProcess(); 135675f74fbSSatoshi Sahara 136675f74fbSSatoshi Sahara // display intro 137675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 138675f74fbSSatoshi Sahara 139675f74fbSSatoshi Sahara // print form to choose diff view type 1400ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 14191e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 142675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 143675f74fbSSatoshi Sahara } 144675f74fbSSatoshi Sahara 145309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 146675f74fbSSatoshi Sahara case 'opacity': 147675f74fbSSatoshi Sahara case 'portions': 1480ea1f71bSSatoshi Sahara $this->showImageDiff(); 149675f74fbSSatoshi Sahara break; 150675f74fbSSatoshi Sahara case 'both': 151675f74fbSSatoshi Sahara default: 1520ea1f71bSSatoshi Sahara $this->showFileDiff(); 153675f74fbSSatoshi Sahara break; 154675f74fbSSatoshi Sahara } 155675f74fbSSatoshi Sahara 1560ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 157675f74fbSSatoshi Sahara echo '</div>'; 158675f74fbSSatoshi Sahara } 1592db397b2SSatoshi Sahara } 1602db397b2SSatoshi Sahara 1612db397b2SSatoshi Sahara /** 162675f74fbSSatoshi Sahara * Print form to choose diff view type 163675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1642db397b2SSatoshi Sahara */ 16591e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1662db397b2SSatoshi Sahara { 1670ea1f71bSSatoshi Sahara // use timestamp for current revision 1680ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']]; 1690ea1f71bSSatoshi Sahara 17091e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 17191e70b5fSSatoshi Sahara 1722db397b2SSatoshi Sahara $form = new Form([ 1732db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1742db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1752db397b2SSatoshi Sahara 'method' => 'get', 1762db397b2SSatoshi Sahara 'class' => 'diffView', 1772db397b2SSatoshi Sahara ]); 1782db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1792db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1802db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 1810ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[0]', $oldRev); 1820ea1f71bSSatoshi Sahara $form->setHiddenField('rev2[1]', $newRev); 1832db397b2SSatoshi Sahara $form->addTagClose('div'); 1842db397b2SSatoshi Sahara echo $form->toHTML(); 18591e70b5fSSatoshi Sahara 18691e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1872db397b2SSatoshi Sahara } 1882db397b2SSatoshi Sahara 189675f74fbSSatoshi Sahara /** 190675f74fbSSatoshi Sahara * Prints two images side by side 191675f74fbSSatoshi Sahara * and slider 192675f74fbSSatoshi Sahara * 193675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 194675f74fbSSatoshi Sahara */ 1950ea1f71bSSatoshi Sahara protected function showImageDiff() 196675f74fbSSatoshi Sahara { 1970ea1f71bSSatoshi Sahara // diff view type: opacity or portions 198675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 1990ea1f71bSSatoshi Sahara 2000ea1f71bSSatoshi Sahara // use '' for current revision 2010ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 202675f74fbSSatoshi Sahara 203675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 2040ea1f71bSSatoshi Sahara $oldRevSize = $this->oldRevInfo['previewSize']; 2050ea1f71bSSatoshi Sahara $newRevSize = $this->newRevInfo['previewSize']; 2063d0f231eSSatoshi Sahara if ($oldRevSize != $newRevSize) { 2073d0f231eSSatoshi Sahara if ($newRevSize[0] > $oldRevSize[0]) { 2083d0f231eSSatoshi Sahara $oldRevSize = $newRevSize; 2092db397b2SSatoshi Sahara } 2102db397b2SSatoshi Sahara } 2112db397b2SSatoshi Sahara 2123d0f231eSSatoshi Sahara $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 2133d0f231eSSatoshi Sahara $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 214675f74fbSSatoshi Sahara 215675f74fbSSatoshi Sahara // slider 2163d0f231eSSatoshi Sahara echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; 217675f74fbSSatoshi Sahara 218675f74fbSSatoshi Sahara // two images in divs 219675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2203d0f231eSSatoshi Sahara echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; 2213d0f231eSSatoshi Sahara echo '<img src="'.$oldRevSrc.'" alt="" />'; 222675f74fbSSatoshi Sahara echo '</div>'; 2233d0f231eSSatoshi Sahara echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; 2243d0f231eSSatoshi Sahara echo '<img src="'.$newRevSrc.'" alt="" />'; 225675f74fbSSatoshi Sahara echo '</div>'; 226675f74fbSSatoshi Sahara echo '</div>'; 227675f74fbSSatoshi Sahara } 228675f74fbSSatoshi Sahara 229675f74fbSSatoshi Sahara /** 230675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 231675f74fbSSatoshi Sahara * 232675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 233675f74fbSSatoshi Sahara */ 2340ea1f71bSSatoshi Sahara protected function showFileDiff() 235675f74fbSSatoshi Sahara { 236a6dd7f90SSatoshi Sahara global $lang; 237a6dd7f90SSatoshi Sahara 2380ea1f71bSSatoshi Sahara $ns = getNS($this->id); 2390ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 2400ea1f71bSSatoshi Sahara 2410ea1f71bSSatoshi Sahara // use '' for current revision 2420ea1f71bSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']]; 2430ea1f71bSSatoshi Sahara 2440ea1f71bSSatoshi Sahara $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); 2450ea1f71bSSatoshi Sahara $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); 2462db397b2SSatoshi Sahara 247179b4660SSatoshi Sahara // display diff view table 2482db397b2SSatoshi Sahara echo '<div class="table">'; 2492db397b2SSatoshi Sahara echo '<table>'; 2502db397b2SSatoshi Sahara echo '<tr>'; 2510ea1f71bSSatoshi Sahara echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>'; 2520ea1f71bSSatoshi Sahara echo '<th>'. $this->newRevInfo['navTitle'] .'</th>'; 253675f74fbSSatoshi Sahara echo '</tr>'; 2542db397b2SSatoshi Sahara 2552db397b2SSatoshi Sahara echo '<tr class="image">'; 2562db397b2SSatoshi Sahara echo '<td>'; 2573d0f231eSSatoshi Sahara media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? 2582db397b2SSatoshi Sahara echo '</td>'; 2592db397b2SSatoshi Sahara 2602db397b2SSatoshi Sahara echo '<td>'; 2613d0f231eSSatoshi Sahara media_preview($this->id, $auth, $newRev, $newRevMeta); 2622db397b2SSatoshi Sahara echo '</td>'; 263675f74fbSSatoshi Sahara echo '</tr>'; 2642db397b2SSatoshi Sahara 2652db397b2SSatoshi Sahara echo '<tr class="actions">'; 2662db397b2SSatoshi Sahara echo '<td>'; 2673d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() 2682db397b2SSatoshi Sahara echo '</td>'; 2692db397b2SSatoshi Sahara 2702db397b2SSatoshi Sahara echo '<td>'; 2713d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $newRev); 2722db397b2SSatoshi Sahara echo '</td>'; 273675f74fbSSatoshi Sahara echo '</tr>'; 2742db397b2SSatoshi Sahara 2753d0f231eSSatoshi Sahara $l_tags = media_file_tags($oldRevMeta); 2763d0f231eSSatoshi Sahara $r_tags = media_file_tags($newRevMeta); 2772db397b2SSatoshi Sahara // FIXME r_tags-only stuff 2782db397b2SSatoshi Sahara foreach ($l_tags as $key => $l_tag) { 2792db397b2SSatoshi Sahara if ($l_tag['value'] != $r_tags[$key]['value']) { 2802db397b2SSatoshi Sahara $r_tags[$key]['highlighted'] = true; 2812db397b2SSatoshi Sahara $l_tags[$key]['highlighted'] = true; 2822db397b2SSatoshi Sahara } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { 2832db397b2SSatoshi Sahara unset($r_tags[$key]); 2842db397b2SSatoshi Sahara unset($l_tags[$key]); 2852db397b2SSatoshi Sahara } 2862db397b2SSatoshi Sahara } 2872db397b2SSatoshi Sahara 2882db397b2SSatoshi Sahara echo '<tr>'; 2892db397b2SSatoshi Sahara foreach (array($l_tags, $r_tags) as $tags) { 290675f74fbSSatoshi Sahara echo '<td>'; 2912db397b2SSatoshi Sahara 2922db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 2932db397b2SSatoshi Sahara foreach ($tags as $tag) { 2942db397b2SSatoshi Sahara $value = cleanText($tag['value']); 2952db397b2SSatoshi Sahara if (!$value) $value = '-'; 2962db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 2972db397b2SSatoshi Sahara echo '<dd>'; 298*f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '<strong>'; 2992db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 3002db397b2SSatoshi Sahara echo dformat($value); 3012db397b2SSatoshi Sahara } else { 3022db397b2SSatoshi Sahara echo hsc($value); 3032db397b2SSatoshi Sahara } 304*f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '</strong>'; 3052db397b2SSatoshi Sahara echo '</dd>'; 3062db397b2SSatoshi Sahara } 307675f74fbSSatoshi Sahara echo '</dl>'; 3082db397b2SSatoshi Sahara 3092db397b2SSatoshi Sahara echo '</td>'; 3102db397b2SSatoshi Sahara } 311675f74fbSSatoshi Sahara echo '</tr>'; 3122db397b2SSatoshi Sahara 313675f74fbSSatoshi Sahara echo '</table>'; 314675f74fbSSatoshi Sahara echo '</div>'; 31563ab9afeSSatoshi Sahara } 31663ab9afeSSatoshi Sahara 317179b4660SSatoshi Sahara /** 318179b4660SSatoshi Sahara * Revision Title for MediaDiff table headline 319179b4660SSatoshi Sahara * 320179b4660SSatoshi Sahara * @param array $info Revision info structure of a media file 321179b4660SSatoshi Sahara * @return string 322179b4660SSatoshi Sahara */ 323179b4660SSatoshi Sahara protected function revisionTitle(array $info) 324179b4660SSatoshi Sahara { 325a6dd7f90SSatoshi Sahara global $lang, $INFO; 326179b4660SSatoshi Sahara 327179b4660SSatoshi Sahara if (isset($info['date'])) { 328179b4660SSatoshi Sahara $rev = $info['date']; 329179b4660SSatoshi Sahara $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' 330179b4660SSatoshi Sahara . dformat($rev).'</a></bdi>'; 331179b4660SSatoshi Sahara } else { 332a6dd7f90SSatoshi Sahara $rev = false; 333179b4660SSatoshi Sahara $title = '—'; 334179b4660SSatoshi Sahara } 335179b4660SSatoshi Sahara if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { 336179b4660SSatoshi Sahara $title .= ' ('.$lang['current'].')'; 337179b4660SSatoshi Sahara } 338179b4660SSatoshi Sahara 339179b4660SSatoshi Sahara // append separator 340179b4660SSatoshi Sahara $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 341179b4660SSatoshi Sahara 342179b4660SSatoshi Sahara // supplement 343179b4660SSatoshi Sahara if (isset($info['date'])) { 344bf3fa5e9SSatoshi Sahara $RevInfo = new RevisionInfo($info); 345bf3fa5e9SSatoshi Sahara $title .= $RevInfo->editSummary().' '.$RevInfo->editor(); 346179b4660SSatoshi Sahara } 347179b4660SSatoshi Sahara return $title; 348179b4660SSatoshi Sahara } 349179b4660SSatoshi Sahara 35063ab9afeSSatoshi Sahara} 351