163ab9afeSSatoshi Sahara<?php 263ab9afeSSatoshi Sahara 363ab9afeSSatoshi Saharanamespace dokuwiki\Ui; 463ab9afeSSatoshi Sahara 563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog; 6*d9c75b22SSatoshi 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{ 18*d9c75b22SSatoshi Sahara /* @var MediaChangeLog */ 19*d9c75b22SSatoshi Sahara protected $changelog; 20*d9c75b22SSatoshi Sahara 2163ab9afeSSatoshi Sahara /** 2263ab9afeSSatoshi Sahara * MediaDiff Ui constructor 2363ab9afeSSatoshi Sahara * 24edb50e6aSSatoshi Sahara * @param string $id media id 2563ab9afeSSatoshi Sahara */ 26edb50e6aSSatoshi Sahara public function __construct($id) 2763ab9afeSSatoshi Sahara { 2830a159abSSatoshi Sahara if ($id) { 2930a159abSSatoshi Sahara throw new \InvalidArgumentException('media id should not be empty!'); 3030a159abSSatoshi Sahara } 31e71e09a6SSatoshi Sahara $this->item = 'media'; 32edb50e6aSSatoshi Sahara 33295564cdSSatoshi Sahara // init preference 34edb50e6aSSatoshi Sahara $this->preference['fromAjax'] = false; // see doluwiki\Ajax::callMediadiff() 35edb50e6aSSatoshi Sahara $this->preference['showIntro'] = false; 3691e70b5fSSatoshi Sahara $this->preference['difftype'] = 'both'; // media diff view type: both, opacity or portions 378068440fSSatoshi Sahara 3830a159abSSatoshi Sahara parent::__construct($id); 398068440fSSatoshi Sahara } 408068440fSSatoshi Sahara 418068440fSSatoshi Sahara /** @inheritdoc */ 428068440fSSatoshi Sahara protected function setChangeLog() 438068440fSSatoshi Sahara { 448068440fSSatoshi Sahara $this->changelog = new MediaChangeLog($this->id); 4563ab9afeSSatoshi Sahara } 4663ab9afeSSatoshi Sahara 47b4b4c5c6SSatoshi Sahara /** @inheritdoc */ 48*d9c75b22SSatoshi Sahara protected function itemFN($id, $rev = '') 49*d9c75b22SSatoshi Sahara { 50*d9c75b22SSatoshi Sahara return mediaFN($id, $rev); 51*d9c75b22SSatoshi Sahara } 52*d9c75b22SSatoshi Sahara 53*d9c75b22SSatoshi Sahara /** @inheritdoc */ 54b4b4c5c6SSatoshi Sahara protected function preProcess() 55b4b4c5c6SSatoshi Sahara { 56b4b4c5c6SSatoshi Sahara parent::preProcess(); 573d0f231eSSatoshi Sahara if (!isset($this->oldRev, $this->newRev)) { 58b4b4c5c6SSatoshi Sahara // no revision was given, compare previous to current 598068440fSSatoshi Sahara $revs = $this->changelog->getRevisions(0, 1); 603d0f231eSSatoshi Sahara $this->oldRev = file_exists(mediaFN($this->id, $revs[0])) ? $revs[0] : ''; 613d0f231eSSatoshi Sahara $this->newRev = ''; 62b4b4c5c6SSatoshi Sahara } 63b4b4c5c6SSatoshi Sahara } 64b4b4c5c6SSatoshi Sahara 6563ab9afeSSatoshi Sahara /** 6663ab9afeSSatoshi Sahara * Shows difference between two revisions of media 67675f74fbSSatoshi Sahara * 68675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 6963ab9afeSSatoshi Sahara */ 70309aaee5SSatoshi Sahara public function show() 7163ab9afeSSatoshi Sahara { 72675f74fbSSatoshi Sahara global $conf; 73675f74fbSSatoshi Sahara 7463ab9afeSSatoshi Sahara $ns = getNS($this->id); 7563ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 76675f74fbSSatoshi Sahara 77675f74fbSSatoshi Sahara if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return ''; 78675f74fbSSatoshi Sahara 79675f74fbSSatoshi Sahara // determine left and right revision 803d0f231eSSatoshi Sahara if (!isset($this->oldRev, $this->newRev)) $this->preProcess(); 813d0f231eSSatoshi Sahara [$oldRev, $newRev] = [$this->oldRev, $this->newRev]; 82675f74fbSSatoshi Sahara 83675f74fbSSatoshi Sahara // prepare event data 84675f74fbSSatoshi Sahara // NOTE: MEDIA_DIFF event does not found in DokuWiki Event List? 85675f74fbSSatoshi Sahara $data = array(); 86675f74fbSSatoshi Sahara $data[0] = $this->id; 873d0f231eSSatoshi Sahara $data[1] = $oldRev; 883d0f231eSSatoshi Sahara $data[2] = $newRev; 89675f74fbSSatoshi Sahara $data[3] = $ns; 90675f74fbSSatoshi Sahara $data[4] = $auth; // permission level 91675f74fbSSatoshi Sahara $data[5] = $this->preference['fromAjax']; 92675f74fbSSatoshi Sahara 93675f74fbSSatoshi Sahara // trigger event 94675f74fbSSatoshi Sahara Event::createAndTrigger('MEDIA_DIFF', $data, null, false); 95675f74fbSSatoshi Sahara 96675f74fbSSatoshi Sahara if (is_array($data) && count($data) === 6) { 97675f74fbSSatoshi Sahara $this->id = $data[0]; 983d0f231eSSatoshi Sahara $oldRev = $data[1]; 993d0f231eSSatoshi Sahara $newRev = $data[2]; 100675f74fbSSatoshi Sahara $ns = $data[3]; 101675f74fbSSatoshi Sahara $auth = $data[4]; 102675f74fbSSatoshi Sahara $this->preference['fromAjax'] = $data[5]; 103675f74fbSSatoshi Sahara } else { 104675f74fbSSatoshi Sahara return ''; 105675f74fbSSatoshi Sahara } 106675f74fbSSatoshi Sahara 10730a159abSSatoshi Sahara $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev)); 10830a159abSSatoshi Sahara $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev)); 109675f74fbSSatoshi Sahara 110675f74fbSSatoshi Sahara $is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 111675f74fbSSatoshi Sahara if ($is_img) { 112675f74fbSSatoshi Sahara // get image width and height for the mediamanager preview panel 1133d0f231eSSatoshi Sahara $oldRevSize = media_image_preview_size($this->id, $oldRev, $oldRevMeta); 1143d0f231eSSatoshi Sahara $newRevSize = media_image_preview_size($this->id, $newRev, $newRevMeta); 115675f74fbSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 1163d0f231eSSatoshi Sahara $is_img = ($oldRevSize && $newRevSize && ($oldRevSize[0] >= 30 || $newRevSize[0] >= 30)); 117675f74fbSSatoshi Sahara } 118675f74fbSSatoshi Sahara 119675f74fbSSatoshi Sahara // determine requested diff view type 120309aaee5SSatoshi Sahara if (!$is_img) { 121309aaee5SSatoshi Sahara $this->preference['difftype'] = 'both'; 122309aaee5SSatoshi Sahara } 123675f74fbSSatoshi Sahara 124675f74fbSSatoshi Sahara // display intro 125675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 126675f74fbSSatoshi Sahara 127675f74fbSSatoshi Sahara // print form to choose diff view type 128675f74fbSSatoshi Sahara if ($is_img && !$this->preference['fromAjax']) { 12991e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 130675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 131675f74fbSSatoshi Sahara } 132675f74fbSSatoshi Sahara 133309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 134675f74fbSSatoshi Sahara case 'opacity': 135675f74fbSSatoshi Sahara case 'portions': 13630a159abSSatoshi Sahara $this->showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize); 137675f74fbSSatoshi Sahara break; 138675f74fbSSatoshi Sahara case 'both': 139675f74fbSSatoshi Sahara default: 1403d0f231eSSatoshi Sahara $this->showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth); 141675f74fbSSatoshi Sahara break; 142675f74fbSSatoshi Sahara } 143675f74fbSSatoshi Sahara 144675f74fbSSatoshi Sahara if ($is_img && !$this->preference['fromAjax']) { 145675f74fbSSatoshi Sahara echo '</div>'; 146675f74fbSSatoshi Sahara } 1472db397b2SSatoshi Sahara } 1482db397b2SSatoshi Sahara 1492db397b2SSatoshi Sahara /** 150675f74fbSSatoshi Sahara * Print form to choose diff view type 151675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1522db397b2SSatoshi Sahara */ 15391e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1542db397b2SSatoshi Sahara { 15591e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 15691e70b5fSSatoshi Sahara 1572db397b2SSatoshi Sahara $form = new Form([ 1582db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1592db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1602db397b2SSatoshi Sahara 'method' => 'get', 1612db397b2SSatoshi Sahara 'class' => 'diffView', 1622db397b2SSatoshi Sahara ]); 1632db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1642db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1652db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 1663d0f231eSSatoshi Sahara $form->setHiddenField('rev2[0]', $this->oldRev ?: 'current'); 1673d0f231eSSatoshi Sahara $form->setHiddenField('rev2[1]', $this->newRev ?: 'current'); 1682db397b2SSatoshi Sahara $form->addTagClose('div'); 1692db397b2SSatoshi Sahara echo $form->toHTML(); 17091e70b5fSSatoshi Sahara 17191e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1722db397b2SSatoshi Sahara } 1732db397b2SSatoshi Sahara 174675f74fbSSatoshi Sahara /** 175675f74fbSSatoshi Sahara * Prints two images side by side 176675f74fbSSatoshi Sahara * and slider 177675f74fbSSatoshi Sahara * 178675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 179675f74fbSSatoshi Sahara * 1803d0f231eSSatoshi Sahara * @param string|int $oldRev revision timestamp, or empty string 1813d0f231eSSatoshi Sahara * @param string|int $newRev revision timestamp, or empty string 1823d0f231eSSatoshi Sahara * @param array $oldRevSize array with width and height 1833d0f231eSSatoshi Sahara * @param array $newRevSize array with width and height 184309aaee5SSatoshi Sahara * @param string $type diff view type: opacity or portions 185675f74fbSSatoshi Sahara */ 1863d0f231eSSatoshi Sahara protected function showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize, $type = null) 187675f74fbSSatoshi Sahara { 188675f74fbSSatoshi Sahara if (!isset($type)) { 189675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 190675f74fbSSatoshi Sahara } 191675f74fbSSatoshi Sahara 192675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 1933d0f231eSSatoshi Sahara if ($oldRevSize != $newRevSize) { 1943d0f231eSSatoshi Sahara if ($newRevSize[0] > $oldRevSize[0]) { 1953d0f231eSSatoshi Sahara $oldRevSize = $newRevSize; 1962db397b2SSatoshi Sahara } 1972db397b2SSatoshi Sahara } 1982db397b2SSatoshi Sahara 1993d0f231eSSatoshi Sahara $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 2003d0f231eSSatoshi Sahara $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]); 201675f74fbSSatoshi Sahara 202675f74fbSSatoshi Sahara // slider 2033d0f231eSSatoshi Sahara echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>'; 204675f74fbSSatoshi Sahara 205675f74fbSSatoshi Sahara // two images in divs 206675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2073d0f231eSSatoshi Sahara echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">'; 2083d0f231eSSatoshi Sahara echo '<img src="'.$oldRevSrc.'" alt="" />'; 209675f74fbSSatoshi Sahara echo '</div>'; 2103d0f231eSSatoshi Sahara echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">'; 2113d0f231eSSatoshi Sahara echo '<img src="'.$newRevSrc.'" alt="" />'; 212675f74fbSSatoshi Sahara echo '</div>'; 213675f74fbSSatoshi Sahara echo '</div>'; 214675f74fbSSatoshi Sahara } 215675f74fbSSatoshi Sahara 216675f74fbSSatoshi Sahara /** 217675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 218675f74fbSSatoshi Sahara * 219675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 220675f74fbSSatoshi Sahara * 2213d0f231eSSatoshi Sahara * @param string|int $oldRev revision timestamp, or empty string 2223d0f231eSSatoshi Sahara * @param string|int $newRev revision timestamp, or empty string 2233d0f231eSSatoshi Sahara * @param JpegMeta $oldRevMeta 2243d0f231eSSatoshi Sahara * @param JpegMeta $newRevMeta 225675f74fbSSatoshi Sahara * @param int $auth permission level 226675f74fbSSatoshi Sahara */ 2273d0f231eSSatoshi Sahara protected function showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth) 228675f74fbSSatoshi Sahara { 229a6dd7f90SSatoshi Sahara global $lang; 230a6dd7f90SSatoshi Sahara 231179b4660SSatoshi Sahara // revison info of older file (left side) 2323d0f231eSSatoshi Sahara $oldRevInfo = $this->getExtendedRevisionInfo($oldRev); 233179b4660SSatoshi Sahara // revison info of newer file (right side) 2343d0f231eSSatoshi Sahara $newRevInfo = $this->getExtendedRevisionInfo($newRev); 2352db397b2SSatoshi Sahara 236179b4660SSatoshi Sahara // display diff view table 2372db397b2SSatoshi Sahara echo '<div class="table">'; 2382db397b2SSatoshi Sahara echo '<table>'; 2392db397b2SSatoshi Sahara echo '<tr>'; 240179b4660SSatoshi Sahara echo '<th>'. $this->revisionTitle($oldRevInfo) .'</th>'; 241179b4660SSatoshi Sahara echo '<th>'. $this->revisionTitle($newRevInfo) .'</th>'; 242675f74fbSSatoshi Sahara echo '</tr>'; 2432db397b2SSatoshi Sahara 2442db397b2SSatoshi Sahara echo '<tr class="image">'; 2452db397b2SSatoshi Sahara echo '<td>'; 2463d0f231eSSatoshi Sahara media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()? 2472db397b2SSatoshi Sahara echo '</td>'; 2482db397b2SSatoshi Sahara 2492db397b2SSatoshi Sahara echo '<td>'; 2503d0f231eSSatoshi Sahara media_preview($this->id, $auth, $newRev, $newRevMeta); 2512db397b2SSatoshi Sahara echo '</td>'; 252675f74fbSSatoshi Sahara echo '</tr>'; 2532db397b2SSatoshi Sahara 2542db397b2SSatoshi Sahara echo '<tr class="actions">'; 2552db397b2SSatoshi Sahara echo '<td>'; 2563d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons() 2572db397b2SSatoshi Sahara echo '</td>'; 2582db397b2SSatoshi Sahara 2592db397b2SSatoshi Sahara echo '<td>'; 2603d0f231eSSatoshi Sahara media_preview_buttons($this->id, $auth, $newRev); 2612db397b2SSatoshi Sahara echo '</td>'; 262675f74fbSSatoshi Sahara echo '</tr>'; 2632db397b2SSatoshi Sahara 2643d0f231eSSatoshi Sahara $l_tags = media_file_tags($oldRevMeta); 2653d0f231eSSatoshi Sahara $r_tags = media_file_tags($newRevMeta); 2662db397b2SSatoshi Sahara // FIXME r_tags-only stuff 2672db397b2SSatoshi Sahara foreach ($l_tags as $key => $l_tag) { 2682db397b2SSatoshi Sahara if ($l_tag['value'] != $r_tags[$key]['value']) { 2692db397b2SSatoshi Sahara $r_tags[$key]['highlighted'] = true; 2702db397b2SSatoshi Sahara $l_tags[$key]['highlighted'] = true; 2712db397b2SSatoshi Sahara } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) { 2722db397b2SSatoshi Sahara unset($r_tags[$key]); 2732db397b2SSatoshi Sahara unset($l_tags[$key]); 2742db397b2SSatoshi Sahara } 2752db397b2SSatoshi Sahara } 2762db397b2SSatoshi Sahara 2772db397b2SSatoshi Sahara echo '<tr>'; 2782db397b2SSatoshi Sahara foreach (array($l_tags, $r_tags) as $tags) { 279675f74fbSSatoshi Sahara echo '<td>'; 2802db397b2SSatoshi Sahara 2812db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 2822db397b2SSatoshi Sahara foreach ($tags as $tag) { 2832db397b2SSatoshi Sahara $value = cleanText($tag['value']); 2842db397b2SSatoshi Sahara if (!$value) $value = '-'; 2852db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 2862db397b2SSatoshi Sahara echo '<dd>'; 2872db397b2SSatoshi Sahara if ($tag['highlighted']) echo '<strong>'; 2882db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 2892db397b2SSatoshi Sahara echo dformat($value); 2902db397b2SSatoshi Sahara } else { 2912db397b2SSatoshi Sahara echo hsc($value); 2922db397b2SSatoshi Sahara } 2932db397b2SSatoshi Sahara if ($tag['highlighted']) echo '</strong>'; 2942db397b2SSatoshi Sahara echo '</dd>'; 2952db397b2SSatoshi Sahara } 296675f74fbSSatoshi Sahara echo '</dl>'; 2972db397b2SSatoshi Sahara 2982db397b2SSatoshi Sahara echo '</td>'; 2992db397b2SSatoshi Sahara } 300675f74fbSSatoshi Sahara echo '</tr>'; 3012db397b2SSatoshi Sahara 302675f74fbSSatoshi Sahara echo '</table>'; 303675f74fbSSatoshi Sahara echo '</div>'; 30463ab9afeSSatoshi Sahara } 30563ab9afeSSatoshi Sahara 306179b4660SSatoshi Sahara /** 307179b4660SSatoshi Sahara * Revision Title for MediaDiff table headline 308179b4660SSatoshi Sahara * 309179b4660SSatoshi Sahara * @param array $info Revision info structure of a media file 310179b4660SSatoshi Sahara * @return string 311179b4660SSatoshi Sahara */ 312179b4660SSatoshi Sahara protected function revisionTitle(array $info) 313179b4660SSatoshi Sahara { 314a6dd7f90SSatoshi Sahara global $lang, $INFO; 315179b4660SSatoshi Sahara 316179b4660SSatoshi Sahara if (isset($info['date'])) { 317179b4660SSatoshi Sahara $rev = $info['date']; 318179b4660SSatoshi Sahara $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">' 319179b4660SSatoshi Sahara . dformat($rev).'</a></bdi>'; 320179b4660SSatoshi Sahara } else { 321a6dd7f90SSatoshi Sahara $rev = false; 322179b4660SSatoshi Sahara $title = '—'; 323179b4660SSatoshi Sahara } 324179b4660SSatoshi Sahara if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) { 325179b4660SSatoshi Sahara $title .= ' ('.$lang['current'].')'; 326179b4660SSatoshi Sahara } 327179b4660SSatoshi Sahara 328179b4660SSatoshi Sahara // append separator 329179b4660SSatoshi Sahara $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />'; 330179b4660SSatoshi Sahara 331179b4660SSatoshi Sahara // supplement 332179b4660SSatoshi Sahara if (isset($info['date'])) { 333179b4660SSatoshi Sahara $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info); 334179b4660SSatoshi Sahara $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor(); 335179b4660SSatoshi Sahara } 336179b4660SSatoshi Sahara return $title; 337179b4660SSatoshi Sahara } 338179b4660SSatoshi Sahara 33963ab9afeSSatoshi Sahara} 340