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 216714d8ceSSatoshi Sahara /* @var RevisionInfo older revision */ 22c02dcaa0SSatoshi Sahara protected $RevInfo1; 236714d8ceSSatoshi Sahara /* @var RevisionInfo newer revision */ 24c02dcaa0SSatoshi Sahara protected $RevInfo2; 250ea1f71bSSatoshi Sahara 260ea1f71bSSatoshi Sahara /* @var bool */ 270ea1f71bSSatoshi Sahara protected $is_img; 280ea1f71bSSatoshi Sahara 2963ab9afeSSatoshi Sahara /** 3063ab9afeSSatoshi Sahara * MediaDiff Ui constructor 3163ab9afeSSatoshi Sahara * 32edb50e6aSSatoshi Sahara * @param string $id media id 3363ab9afeSSatoshi Sahara */ 34edb50e6aSSatoshi Sahara public function __construct($id) 3563ab9afeSSatoshi Sahara { 364557f463SSatoshi Sahara if (!isset($id)) { 3779a2d784SGerrit Uitslag throw new InvalidArgumentException('media id should not be empty!'); 3830a159abSSatoshi Sahara } 39edb50e6aSSatoshi Sahara 40295564cdSSatoshi Sahara // init preference 416527839fSSatoshi Sahara $this->preference['fromAjax'] = false; // see dokuwiki\Ajax::callMediadiff() 42edb50e6aSSatoshi Sahara $this->preference['showIntro'] = false; 430ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions 448068440fSSatoshi Sahara 4530a159abSSatoshi Sahara parent::__construct($id); 468068440fSSatoshi Sahara } 478068440fSSatoshi Sahara 488068440fSSatoshi Sahara /** @inheritdoc */ 498068440fSSatoshi Sahara protected function setChangeLog() 508068440fSSatoshi Sahara { 518068440fSSatoshi Sahara $this->changelog = new MediaChangeLog($this->id); 5263ab9afeSSatoshi Sahara } 5363ab9afeSSatoshi Sahara 540ea1f71bSSatoshi Sahara /** 550ea1f71bSSatoshi Sahara * Handle requested revision(s) and diff view preferences 560ea1f71bSSatoshi Sahara * 570ea1f71bSSatoshi Sahara * @return void 580ea1f71bSSatoshi Sahara */ 590ea1f71bSSatoshi Sahara protected function handle() 60b4b4c5c6SSatoshi Sahara { 610ea1f71bSSatoshi Sahara global $INPUT; 620ea1f71bSSatoshi Sahara 636714d8ceSSatoshi Sahara // retrieve requested rev or rev2 640ea1f71bSSatoshi Sahara parent::handle(); 650ea1f71bSSatoshi Sahara 660ea1f71bSSatoshi Sahara // requested diff view type 670ea1f71bSSatoshi Sahara if ($INPUT->has('difftype')) { 680ea1f71bSSatoshi Sahara $this->preference['difftype'] = $INPUT->str('difftype'); 690ea1f71bSSatoshi Sahara } 70b4b4c5c6SSatoshi Sahara } 71b4b4c5c6SSatoshi Sahara 7263ab9afeSSatoshi Sahara /** 730ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 740ea1f71bSSatoshi Sahara */ 750ea1f71bSSatoshi Sahara protected function preProcess() 760ea1f71bSSatoshi Sahara { 770ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 780ea1f71bSSatoshi Sahara 796714d8ceSSatoshi Sahara // create revision info object for older and newer sides 80c02dcaa0SSatoshi Sahara // RevInfo1 : older, left side 81c02dcaa0SSatoshi Sahara // RevInfo2 : newer, right side 82*921c2ae3STherealperO 83*921c2ae3STherealperO $changelogRev1 = $changelog->getRevisionInfo($this->rev1); 84*921c2ae3STherealperO $changelogRev2 = $changelog->getRevisionInfo($this->rev2); 85*921c2ae3STherealperO $changelogRev1['media'] = $changelogRev2['media'] = true; 86*921c2ae3STherealperO 87*921c2ae3STherealperO $this->RevInfo1 = new RevisionInfo($changelogRev1); 88*921c2ae3STherealperO $this->RevInfo2 = new RevisionInfo($changelogRev2); 890ea1f71bSSatoshi Sahara 900ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 910ea1f71bSSatoshi Sahara 92c02dcaa0SSatoshi Sahara foreach ([$this->RevInfo1, $this->RevInfo2] as $RevInfo) { 93c02dcaa0SSatoshi Sahara $isCurrent = $changelog->isCurrentRevision($RevInfo->val('date')); 94c02dcaa0SSatoshi Sahara $RevInfo->isCurrent($isCurrent); 950ea1f71bSSatoshi Sahara 960ea1f71bSSatoshi Sahara if ($this->is_img) { 97c02dcaa0SSatoshi Sahara $rev = $isCurrent ? '' : $RevInfo->val('date'); 980ea1f71bSSatoshi Sahara $meta = new JpegMeta(mediaFN($this->id, $rev)); 990ea1f71bSSatoshi Sahara // get image width and height for the media manager preview panel 100c02dcaa0SSatoshi Sahara $RevInfo->append([ 1016714d8ceSSatoshi Sahara 'previewSize' => media_image_preview_size($this->id, $rev, $meta) 1026714d8ceSSatoshi Sahara ]); 1030ea1f71bSSatoshi Sahara } 1040ea1f71bSSatoshi Sahara } 1050ea1f71bSSatoshi Sahara 1060ea1f71bSSatoshi Sahara // re-check image, ensure minimum image width for showImageDiff() 1070ea1f71bSSatoshi Sahara $this->is_img = ($this->is_img 108c02dcaa0SSatoshi Sahara && ($this->RevInfo1->val('previewSize')[0] ?? 0) >= 30 109c02dcaa0SSatoshi Sahara && ($this->RevInfo2->val('previewSize')[0] ?? 0) >= 30 1100ea1f71bSSatoshi Sahara ); 1110ea1f71bSSatoshi Sahara // adjust requested diff view type 1120ea1f71bSSatoshi Sahara if (!$this->is_img) { 1130ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; 1140ea1f71bSSatoshi Sahara } 1150ea1f71bSSatoshi Sahara } 1160ea1f71bSSatoshi Sahara 1170ea1f71bSSatoshi Sahara 1180ea1f71bSSatoshi Sahara /** 11963ab9afeSSatoshi Sahara * Shows difference between two revisions of media 120675f74fbSSatoshi Sahara * 121675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 12263ab9afeSSatoshi Sahara */ 123309aaee5SSatoshi Sahara public function show() 12463ab9afeSSatoshi Sahara { 125675f74fbSSatoshi Sahara global $conf; 126675f74fbSSatoshi Sahara 12763ab9afeSSatoshi Sahara $ns = getNS($this->id); 12863ab9afeSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 129675f74fbSSatoshi Sahara 13079a2d784SGerrit Uitslag if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return; 131675f74fbSSatoshi Sahara 1320ea1f71bSSatoshi Sahara // retrieve form parameters: rev, rev2, difftype 1330ea1f71bSSatoshi Sahara $this->handle(); 1340ea1f71bSSatoshi Sahara // prepare revision info of comparison pair 1350ea1f71bSSatoshi Sahara $this->preProcess(); 136675f74fbSSatoshi Sahara 137675f74fbSSatoshi Sahara // display intro 138675f74fbSSatoshi Sahara if ($this->preference['showIntro']) echo p_locale_xhtml('diff'); 139675f74fbSSatoshi Sahara 140675f74fbSSatoshi Sahara // print form to choose diff view type 1410ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 14291e70b5fSSatoshi Sahara $this->showDiffViewSelector(); 143675f74fbSSatoshi Sahara echo '<div id="mediamanager__diff" >'; 144675f74fbSSatoshi Sahara } 145675f74fbSSatoshi Sahara 146309aaee5SSatoshi Sahara switch ($this->preference['difftype']) { 147675f74fbSSatoshi Sahara case 'opacity': 148675f74fbSSatoshi Sahara case 'portions': 1490ea1f71bSSatoshi Sahara $this->showImageDiff(); 150675f74fbSSatoshi Sahara break; 151675f74fbSSatoshi Sahara case 'both': 152675f74fbSSatoshi Sahara default: 1530ea1f71bSSatoshi Sahara $this->showFileDiff(); 154675f74fbSSatoshi Sahara break; 155675f74fbSSatoshi Sahara } 156675f74fbSSatoshi Sahara 1570ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 158675f74fbSSatoshi Sahara echo '</div>'; 159675f74fbSSatoshi Sahara } 1602db397b2SSatoshi Sahara } 1612db397b2SSatoshi Sahara 1622db397b2SSatoshi Sahara /** 163675f74fbSSatoshi Sahara * Print form to choose diff view type 164675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1652db397b2SSatoshi Sahara */ 16691e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1672db397b2SSatoshi Sahara { 168c02dcaa0SSatoshi Sahara // use timestamp for current revision, date may be false when revisions < 2 169c02dcaa0SSatoshi Sahara [$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')]; 1700ea1f71bSSatoshi Sahara 17191e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 17291e70b5fSSatoshi Sahara 1732db397b2SSatoshi Sahara $form = new Form([ 1742db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1752db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1762db397b2SSatoshi Sahara 'method' => 'get', 1772db397b2SSatoshi Sahara 'class' => 'diffView', 1782db397b2SSatoshi Sahara ]); 1792db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1802db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1812db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 182c02dcaa0SSatoshi Sahara $form->setHiddenField('rev2[0]', $rev1); 183c02dcaa0SSatoshi Sahara $form->setHiddenField('rev2[1]', $rev2); 1842db397b2SSatoshi Sahara $form->addTagClose('div'); 1852db397b2SSatoshi Sahara echo $form->toHTML(); 18691e70b5fSSatoshi Sahara 18791e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1882db397b2SSatoshi Sahara } 1892db397b2SSatoshi Sahara 190675f74fbSSatoshi Sahara /** 191675f74fbSSatoshi Sahara * Prints two images side by side 192675f74fbSSatoshi Sahara * and slider 193675f74fbSSatoshi Sahara * 194675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 195675f74fbSSatoshi Sahara */ 1960ea1f71bSSatoshi Sahara protected function showImageDiff() 197675f74fbSSatoshi Sahara { 198c02dcaa0SSatoshi Sahara $rev1 = $this->RevInfo1->isCurrent() ? '' : $this->RevInfo1->val('date'); 199c02dcaa0SSatoshi Sahara $rev2 = $this->RevInfo2->isCurrent() ? '' : $this->RevInfo2->val('date'); 2006714d8ceSSatoshi Sahara 2010ea1f71bSSatoshi Sahara // diff view type: opacity or portions 202675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 2030ea1f71bSSatoshi Sahara 204675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 205c02dcaa0SSatoshi Sahara $rev1Size = $this->RevInfo1->val('previewSize'); 206c02dcaa0SSatoshi Sahara $rev2Size = $this->RevInfo2->val('previewSize'); 2076714d8ceSSatoshi Sahara if ($rev1Size != $rev2Size) { 2086714d8ceSSatoshi Sahara if ($rev2Size[0] > $rev1Size[0]) { 2096714d8ceSSatoshi Sahara $rev1Size = $rev2Size; 2102db397b2SSatoshi Sahara } 2112db397b2SSatoshi Sahara } 2122db397b2SSatoshi Sahara 2136714d8ceSSatoshi Sahara $rev1Src = ml($this->id, ['rev' => $rev1, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]); 2146714d8ceSSatoshi Sahara $rev2Src = ml($this->id, ['rev' => $rev2, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]); 215675f74fbSSatoshi Sahara 216675f74fbSSatoshi Sahara // slider 2176714d8ceSSatoshi Sahara echo '<div class="slider" style="max-width: '.($rev1Size[0]-20).'px;" ></div>'; 218675f74fbSSatoshi Sahara 219675f74fbSSatoshi Sahara // two images in divs 220675f74fbSSatoshi Sahara echo '<div class="imageDiff '.$type.'">'; 2216714d8ceSSatoshi Sahara echo '<div class="image1" style="max-width: '.$rev1Size[0].'px;">'; 2226714d8ceSSatoshi Sahara echo '<img src="'.$rev1Src.'" alt="" />'; 223675f74fbSSatoshi Sahara echo '</div>'; 2246714d8ceSSatoshi Sahara echo '<div class="image2" style="max-width: '.$rev1Size[0].'px;">'; 2256714d8ceSSatoshi Sahara echo '<img src="'.$rev2Src.'" alt="" />'; 226675f74fbSSatoshi Sahara echo '</div>'; 227675f74fbSSatoshi Sahara echo '</div>'; 228675f74fbSSatoshi Sahara } 229675f74fbSSatoshi Sahara 230675f74fbSSatoshi Sahara /** 231675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 232675f74fbSSatoshi Sahara * 233675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 234675f74fbSSatoshi Sahara */ 2350ea1f71bSSatoshi Sahara protected function showFileDiff() 236675f74fbSSatoshi Sahara { 237a6dd7f90SSatoshi Sahara global $lang; 238a6dd7f90SSatoshi Sahara 2390ea1f71bSSatoshi Sahara $ns = getNS($this->id); 2400ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 2410ea1f71bSSatoshi Sahara 242c02dcaa0SSatoshi Sahara $rev1 = $this->RevInfo1->isCurrent() ? '' : (int)$this->RevInfo1->val('date'); 243c02dcaa0SSatoshi Sahara $rev2 = $this->RevInfo2->isCurrent() ? '' : (int)$this->RevInfo2->val('date'); 2446714d8ceSSatoshi Sahara 2456714d8ceSSatoshi Sahara // revision title 246c02dcaa0SSatoshi Sahara $rev1Title = trim($this->RevInfo1->showRevisionTitle() .' '. $this->RevInfo1->showCurrentIndicator()); 247c02dcaa0SSatoshi Sahara $rev1Summary = ($this->RevInfo1->val('date')) 248c02dcaa0SSatoshi Sahara ? $this->RevInfo1->showEditSummary() .' '. $this->RevInfo1->showEditor() 2496714d8ceSSatoshi Sahara : ''; 250c02dcaa0SSatoshi Sahara $rev2Title = trim($this->RevInfo2->showRevisionTitle() .' '. $this->RevInfo2->showCurrentIndicator()); 251c02dcaa0SSatoshi Sahara $rev2Summary = ($this->RevInfo2->val('date')) 252c02dcaa0SSatoshi Sahara ? $this->RevInfo2->showEditSummary() .' '. $this->RevInfo2->showEditor() 2536714d8ceSSatoshi Sahara : ''; 2546714d8ceSSatoshi Sahara 2556714d8ceSSatoshi Sahara $rev1Meta = new JpegMeta(mediaFN($this->id, $rev1)); 2566714d8ceSSatoshi Sahara $rev2Meta = new JpegMeta(mediaFN($this->id, $rev2)); 2572db397b2SSatoshi Sahara 258179b4660SSatoshi Sahara // display diff view table 2592db397b2SSatoshi Sahara echo '<div class="table">'; 2602db397b2SSatoshi Sahara echo '<table>'; 2612db397b2SSatoshi Sahara echo '<tr>'; 2623712ae9eSSatoshi Sahara echo '<th>'. $rev1Title .' '. $rev1Summary .'</th>'; 2633712ae9eSSatoshi Sahara echo '<th>'. $rev2Title .' '. $rev2Summary .'</th>'; 264675f74fbSSatoshi Sahara echo '</tr>'; 2652db397b2SSatoshi Sahara 2662db397b2SSatoshi Sahara echo '<tr class="image">'; 2672db397b2SSatoshi Sahara echo '<td>'; 2686714d8ceSSatoshi Sahara media_preview($this->id, $auth, $rev1, $rev1Meta); // $auth not used in media_preview()? 2692db397b2SSatoshi Sahara echo '</td>'; 2702db397b2SSatoshi Sahara 2712db397b2SSatoshi Sahara echo '<td>'; 2726714d8ceSSatoshi Sahara media_preview($this->id, $auth, $rev2, $rev2Meta); 2732db397b2SSatoshi Sahara echo '</td>'; 274675f74fbSSatoshi Sahara echo '</tr>'; 2752db397b2SSatoshi Sahara 2762db397b2SSatoshi Sahara echo '<tr class="actions">'; 2772db397b2SSatoshi Sahara echo '<td>'; 2786714d8ceSSatoshi Sahara media_preview_buttons($this->id, $auth, $rev1); // $auth used in media_preview_buttons() 2792db397b2SSatoshi Sahara echo '</td>'; 2802db397b2SSatoshi Sahara 2812db397b2SSatoshi Sahara echo '<td>'; 2826714d8ceSSatoshi Sahara media_preview_buttons($this->id, $auth, $rev2); 2832db397b2SSatoshi Sahara echo '</td>'; 284675f74fbSSatoshi Sahara echo '</tr>'; 2852db397b2SSatoshi Sahara 2866714d8ceSSatoshi Sahara $rev1Tags = media_file_tags($rev1Meta); 2876714d8ceSSatoshi Sahara $rev2Tags = media_file_tags($rev2Meta); 2886714d8ceSSatoshi Sahara // FIXME rev2Tags-only stuff ignored 2896714d8ceSSatoshi Sahara foreach ($rev1Tags as $key => $tag) { 2906714d8ceSSatoshi Sahara if ($tag['value'] != $rev2Tags[$key]['value']) { 2916714d8ceSSatoshi Sahara $rev2Tags[$key]['highlighted'] = true; 2926714d8ceSSatoshi Sahara $rev1Tags[$key]['highlighted'] = true; 2936714d8ceSSatoshi Sahara } elseif (!$tag['value'] || !$rev2Tags[$key]['value']) { 2946714d8ceSSatoshi Sahara unset($rev2Tags[$key]); 2956714d8ceSSatoshi Sahara unset($rev1Tags[$key]); 2962db397b2SSatoshi Sahara } 2972db397b2SSatoshi Sahara } 2982db397b2SSatoshi Sahara 2992db397b2SSatoshi Sahara echo '<tr>'; 3006714d8ceSSatoshi Sahara foreach ([$rev1Tags, $rev2Tags] as $tags) { 301675f74fbSSatoshi Sahara echo '<td>'; 3022db397b2SSatoshi Sahara 3032db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 3042db397b2SSatoshi Sahara foreach ($tags as $tag) { 3052db397b2SSatoshi Sahara $value = cleanText($tag['value']); 3062db397b2SSatoshi Sahara if (!$value) $value = '-'; 3072db397b2SSatoshi Sahara echo '<dt>'.$lang[$tag['tag'][1]].'</dt>'; 3082db397b2SSatoshi Sahara echo '<dd>'; 309f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '<strong>'; 3102db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 3112db397b2SSatoshi Sahara echo dformat($value); 3122db397b2SSatoshi Sahara } else { 3132db397b2SSatoshi Sahara echo hsc($value); 3142db397b2SSatoshi Sahara } 315f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '</strong>'; 3162db397b2SSatoshi Sahara echo '</dd>'; 3172db397b2SSatoshi Sahara } 318675f74fbSSatoshi Sahara echo '</dl>'; 3192db397b2SSatoshi Sahara 3202db397b2SSatoshi Sahara echo '</td>'; 3212db397b2SSatoshi Sahara } 322675f74fbSSatoshi Sahara echo '</tr>'; 3232db397b2SSatoshi Sahara 324675f74fbSSatoshi Sahara echo '</table>'; 325675f74fbSSatoshi Sahara echo '</div>'; 32663ab9afeSSatoshi Sahara } 32763ab9afeSSatoshi Sahara 32863ab9afeSSatoshi Sahara} 329