163ab9afeSSatoshi Sahara<?php 263ab9afeSSatoshi Sahara 363ab9afeSSatoshi Saharanamespace dokuwiki\Ui; 463ab9afeSSatoshi Sahara 563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog; 6bf3fa5e9SSatoshi Saharause dokuwiki\ChangeLog\RevisionInfo; 7*dd9e8e5eSAndreas Gohruse dokuwiki\File\MediaFile; 863ab9afeSSatoshi Saharause dokuwiki\Form\Form; 9*dd9e8e5eSAndreas Gohruse dokuwiki\Ui\Media\Display; 1079a2d784SGerrit Uitslaguse InvalidArgumentException; 1130a159abSSatoshi Saharause JpegMeta; 1263ab9afeSSatoshi Sahara 1363ab9afeSSatoshi Sahara/** 1463ab9afeSSatoshi Sahara * DokuWiki MediaDiff Interface 1563ab9afeSSatoshi Sahara * 1663ab9afeSSatoshi Sahara * @package dokuwiki\Ui 1763ab9afeSSatoshi Sahara */ 1863ab9afeSSatoshi Saharaclass MediaDiff extends Diff 1963ab9afeSSatoshi Sahara{ 20d9c75b22SSatoshi Sahara /* @var MediaChangeLog */ 21d9c75b22SSatoshi Sahara protected $changelog; 22d9c75b22SSatoshi Sahara 236714d8ceSSatoshi Sahara /* @var RevisionInfo older revision */ 24c02dcaa0SSatoshi Sahara protected $RevInfo1; 256714d8ceSSatoshi Sahara /* @var RevisionInfo newer revision */ 26c02dcaa0SSatoshi Sahara protected $RevInfo2; 270ea1f71bSSatoshi Sahara 280ea1f71bSSatoshi Sahara /* @var bool */ 290ea1f71bSSatoshi Sahara protected $is_img; 300ea1f71bSSatoshi Sahara 3163ab9afeSSatoshi Sahara /** 3263ab9afeSSatoshi Sahara * MediaDiff Ui constructor 3363ab9afeSSatoshi Sahara * 34edb50e6aSSatoshi Sahara * @param string $id media id 3563ab9afeSSatoshi Sahara */ 36edb50e6aSSatoshi Sahara public function __construct($id) 3763ab9afeSSatoshi Sahara { 384557f463SSatoshi Sahara if (!isset($id)) { 3979a2d784SGerrit Uitslag throw new InvalidArgumentException('media id should not be empty!'); 4030a159abSSatoshi Sahara } 41edb50e6aSSatoshi Sahara 42295564cdSSatoshi Sahara // init preference 436527839fSSatoshi Sahara $this->preference['fromAjax'] = false; // see dokuwiki\Ajax::callMediadiff() 44edb50e6aSSatoshi Sahara $this->preference['showIntro'] = false; 450ea1f71bSSatoshi Sahara $this->preference['difftype'] = 'both'; // diff view type: both, opacity or portions 468068440fSSatoshi Sahara 4730a159abSSatoshi Sahara parent::__construct($id); 488068440fSSatoshi Sahara } 498068440fSSatoshi Sahara 508068440fSSatoshi Sahara /** @inheritdoc */ 518068440fSSatoshi Sahara protected function setChangeLog() 528068440fSSatoshi Sahara { 538068440fSSatoshi Sahara $this->changelog = new MediaChangeLog($this->id); 5463ab9afeSSatoshi Sahara } 5563ab9afeSSatoshi Sahara 560ea1f71bSSatoshi Sahara /** 570ea1f71bSSatoshi Sahara * Handle requested revision(s) and diff view preferences 580ea1f71bSSatoshi Sahara * 590ea1f71bSSatoshi Sahara * @return void 600ea1f71bSSatoshi Sahara */ 610ea1f71bSSatoshi Sahara protected function handle() 62b4b4c5c6SSatoshi Sahara { 630ea1f71bSSatoshi Sahara global $INPUT; 640ea1f71bSSatoshi Sahara 656714d8ceSSatoshi Sahara // retrieve requested rev or rev2 660ea1f71bSSatoshi Sahara parent::handle(); 670ea1f71bSSatoshi Sahara 680ea1f71bSSatoshi Sahara // requested diff view type 690ea1f71bSSatoshi Sahara if ($INPUT->has('difftype')) { 700ea1f71bSSatoshi Sahara $this->preference['difftype'] = $INPUT->str('difftype'); 710ea1f71bSSatoshi Sahara } 72b4b4c5c6SSatoshi Sahara } 73b4b4c5c6SSatoshi Sahara 7463ab9afeSSatoshi Sahara /** 750ea1f71bSSatoshi Sahara * Prepare revision info of comparison pair 760ea1f71bSSatoshi Sahara */ 770ea1f71bSSatoshi Sahara protected function preProcess() 780ea1f71bSSatoshi Sahara { 790ea1f71bSSatoshi Sahara $changelog =& $this->changelog; 800ea1f71bSSatoshi Sahara 816714d8ceSSatoshi Sahara // create revision info object for older and newer sides 82c02dcaa0SSatoshi Sahara // RevInfo1 : older, left side 83c02dcaa0SSatoshi Sahara // RevInfo2 : newer, right side 84921c2ae3STherealperO 85921c2ae3STherealperO $changelogRev1 = $changelog->getRevisionInfo($this->rev1); 86921c2ae3STherealperO $changelogRev2 = $changelog->getRevisionInfo($this->rev2); 87921c2ae3STherealperO 88921c2ae3STherealperO $this->RevInfo1 = new RevisionInfo($changelogRev1); 89921c2ae3STherealperO $this->RevInfo2 = new RevisionInfo($changelogRev2); 900ea1f71bSSatoshi Sahara 910ea1f71bSSatoshi Sahara $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id); 920ea1f71bSSatoshi Sahara 93c02dcaa0SSatoshi Sahara foreach ([$this->RevInfo1, $this->RevInfo2] as $RevInfo) { 94c02dcaa0SSatoshi Sahara $isCurrent = $changelog->isCurrentRevision($RevInfo->val('date')); 95c02dcaa0SSatoshi Sahara $RevInfo->isCurrent($isCurrent); 960ea1f71bSSatoshi Sahara 970ea1f71bSSatoshi Sahara if ($this->is_img) { 98c02dcaa0SSatoshi Sahara $rev = $isCurrent ? '' : $RevInfo->val('date'); 99*dd9e8e5eSAndreas Gohr // get display dimensions for the media manager preview panel 100c02dcaa0SSatoshi Sahara $RevInfo->append([ 101*dd9e8e5eSAndreas Gohr 'previewSize' => (new MediaFile($this->id, $rev))->getDisplayDimensions(500, 500, false) 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 146093fe67eSAndreas Gohr match ($this->preference['difftype']) { 147093fe67eSAndreas Gohr 'opacity', 'portions' => $this->showImageDiff(), 148093fe67eSAndreas Gohr default => $this->showFileDiff(), 149093fe67eSAndreas Gohr }; 150675f74fbSSatoshi Sahara 1510ea1f71bSSatoshi Sahara if ($this->is_img && !$this->preference['fromAjax']) { 152675f74fbSSatoshi Sahara echo '</div>'; 153675f74fbSSatoshi Sahara } 1542db397b2SSatoshi Sahara } 1552db397b2SSatoshi Sahara 1562db397b2SSatoshi Sahara /** 157675f74fbSSatoshi Sahara * Print form to choose diff view type 158675f74fbSSatoshi Sahara * the dropdown is to be added through JavaScript, see lib/scripts/media.js 1592db397b2SSatoshi Sahara */ 16091e70b5fSSatoshi Sahara protected function showDiffViewSelector() 1612db397b2SSatoshi Sahara { 162c02dcaa0SSatoshi Sahara // use timestamp for current revision, date may be false when revisions < 2 163c02dcaa0SSatoshi Sahara [$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')]; 1640ea1f71bSSatoshi Sahara 16591e70b5fSSatoshi Sahara echo '<div class="diffoptions group">'; 16691e70b5fSSatoshi Sahara 1672db397b2SSatoshi Sahara $form = new Form([ 1682db397b2SSatoshi Sahara 'id' => 'mediamanager__form_diffview', 1692db397b2SSatoshi Sahara 'action' => media_managerURL([], '&'), 1702db397b2SSatoshi Sahara 'method' => 'get', 1712db397b2SSatoshi Sahara 'class' => 'diffView', 1722db397b2SSatoshi Sahara ]); 1732db397b2SSatoshi Sahara $form->addTagOpen('div')->addClass('no'); 1742db397b2SSatoshi Sahara $form->setHiddenField('sectok', null); 1752db397b2SSatoshi Sahara $form->setHiddenField('mediado', 'diff'); 176c02dcaa0SSatoshi Sahara $form->setHiddenField('rev2[0]', $rev1); 177c02dcaa0SSatoshi Sahara $form->setHiddenField('rev2[1]', $rev2); 1782db397b2SSatoshi Sahara $form->addTagClose('div'); 1792db397b2SSatoshi Sahara echo $form->toHTML(); 18091e70b5fSSatoshi Sahara 18191e70b5fSSatoshi Sahara echo '</div>'; // .diffoptions 1822db397b2SSatoshi Sahara } 1832db397b2SSatoshi Sahara 184675f74fbSSatoshi Sahara /** 185675f74fbSSatoshi Sahara * Prints two images side by side 186675f74fbSSatoshi Sahara * and slider 187675f74fbSSatoshi Sahara * 188675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 189675f74fbSSatoshi Sahara */ 1900ea1f71bSSatoshi Sahara protected function showImageDiff() 191675f74fbSSatoshi Sahara { 192c02dcaa0SSatoshi Sahara $rev1 = $this->RevInfo1->isCurrent() ? '' : $this->RevInfo1->val('date'); 193c02dcaa0SSatoshi Sahara $rev2 = $this->RevInfo2->isCurrent() ? '' : $this->RevInfo2->val('date'); 1946714d8ceSSatoshi Sahara 1950ea1f71bSSatoshi Sahara // diff view type: opacity or portions 196675f74fbSSatoshi Sahara $type = $this->preference['difftype']; 1970ea1f71bSSatoshi Sahara 198675f74fbSSatoshi Sahara // adjust image width, right side (newer) has priority 199c02dcaa0SSatoshi Sahara $rev1Size = $this->RevInfo1->val('previewSize'); 200c02dcaa0SSatoshi Sahara $rev2Size = $this->RevInfo2->val('previewSize'); 2016714d8ceSSatoshi Sahara if ($rev1Size != $rev2Size) { 2026714d8ceSSatoshi Sahara if ($rev2Size[0] > $rev1Size[0]) { 2036714d8ceSSatoshi Sahara $rev1Size = $rev2Size; 2042db397b2SSatoshi Sahara } 2052db397b2SSatoshi Sahara } 2062db397b2SSatoshi Sahara 207*dd9e8e5eSAndreas Gohr $rev1Src = ml($this->id, ['rev' => $rev1, 'h' => $rev1Size[1], 'w' => $rev1Size[0], 'fit' => 1]); 208*dd9e8e5eSAndreas Gohr $rev2Src = ml($this->id, ['rev' => $rev2, 'h' => $rev1Size[1], 'w' => $rev1Size[0], 'fit' => 1]); 209675f74fbSSatoshi Sahara 210675f74fbSSatoshi Sahara // slider 2116714d8ceSSatoshi Sahara echo '<div class="slider" style="max-width: ' . ($rev1Size[0] - 20) . 'px;" ></div>'; 212675f74fbSSatoshi Sahara 213675f74fbSSatoshi Sahara // two images in divs 214675f74fbSSatoshi Sahara echo '<div class="imageDiff ' . $type . '">'; 2156714d8ceSSatoshi Sahara echo '<div class="image1" style="max-width: ' . $rev1Size[0] . 'px;">'; 2166714d8ceSSatoshi Sahara echo '<img src="' . $rev1Src . '" alt="" />'; 217675f74fbSSatoshi Sahara echo '</div>'; 2186714d8ceSSatoshi Sahara echo '<div class="image2" style="max-width: ' . $rev1Size[0] . 'px;">'; 2196714d8ceSSatoshi Sahara echo '<img src="' . $rev2Src . '" alt="" />'; 220675f74fbSSatoshi Sahara echo '</div>'; 221675f74fbSSatoshi Sahara echo '</div>'; 222675f74fbSSatoshi Sahara } 223675f74fbSSatoshi Sahara 224675f74fbSSatoshi Sahara /** 225675f74fbSSatoshi Sahara * Shows difference between two revisions of media file 226675f74fbSSatoshi Sahara * 227675f74fbSSatoshi Sahara * @author Kate Arzamastseva <pshns@ukr.net> 228675f74fbSSatoshi Sahara */ 2290ea1f71bSSatoshi Sahara protected function showFileDiff() 230675f74fbSSatoshi Sahara { 231a6dd7f90SSatoshi Sahara global $lang; 232a6dd7f90SSatoshi Sahara 2330ea1f71bSSatoshi Sahara $ns = getNS($this->id); 2340ea1f71bSSatoshi Sahara $auth = auth_quickaclcheck("$ns:*"); 2350ea1f71bSSatoshi Sahara 236c02dcaa0SSatoshi Sahara $rev1 = $this->RevInfo1->isCurrent() ? '' : (int)$this->RevInfo1->val('date'); 237c02dcaa0SSatoshi Sahara $rev2 = $this->RevInfo2->isCurrent() ? '' : (int)$this->RevInfo2->val('date'); 2386714d8ceSSatoshi Sahara 2396714d8ceSSatoshi Sahara // revision title 240c02dcaa0SSatoshi Sahara $rev1Title = trim($this->RevInfo1->showRevisionTitle() . ' ' . $this->RevInfo1->showCurrentIndicator()); 241c02dcaa0SSatoshi Sahara $rev1Summary = ($this->RevInfo1->val('date')) 242c02dcaa0SSatoshi Sahara ? $this->RevInfo1->showEditSummary() . ' ' . $this->RevInfo1->showEditor() 2436714d8ceSSatoshi Sahara : ''; 244c02dcaa0SSatoshi Sahara $rev2Title = trim($this->RevInfo2->showRevisionTitle() . ' ' . $this->RevInfo2->showCurrentIndicator()); 245c02dcaa0SSatoshi Sahara $rev2Summary = ($this->RevInfo2->val('date')) 246c02dcaa0SSatoshi Sahara ? $this->RevInfo2->showEditSummary() . ' ' . $this->RevInfo2->showEditor() 2476714d8ceSSatoshi Sahara : ''; 2486714d8ceSSatoshi Sahara 2496714d8ceSSatoshi Sahara $rev1Meta = new JpegMeta(mediaFN($this->id, $rev1)); 2506714d8ceSSatoshi Sahara $rev2Meta = new JpegMeta(mediaFN($this->id, $rev2)); 2512db397b2SSatoshi Sahara 252179b4660SSatoshi Sahara // display diff view table 2532db397b2SSatoshi Sahara echo '<div class="table">'; 2542db397b2SSatoshi Sahara echo '<table>'; 2552db397b2SSatoshi Sahara echo '<tr>'; 2563712ae9eSSatoshi Sahara echo '<th>' . $rev1Title . ' ' . $rev1Summary . '</th>'; 2573712ae9eSSatoshi Sahara echo '<th>' . $rev2Title . ' ' . $rev2Summary . '</th>'; 258675f74fbSSatoshi Sahara echo '</tr>'; 2592db397b2SSatoshi Sahara 2602db397b2SSatoshi Sahara echo '<tr class="image">'; 2612db397b2SSatoshi Sahara echo '<td>'; 262*dd9e8e5eSAndreas Gohr echo (new Display(new MediaFile($this->id, $rev1)))->getDetailHtml(); 2632db397b2SSatoshi Sahara echo '</td>'; 2642db397b2SSatoshi Sahara 2652db397b2SSatoshi Sahara echo '<td>'; 266*dd9e8e5eSAndreas Gohr echo (new Display(new MediaFile($this->id, $rev2)))->getDetailHtml(); 2672db397b2SSatoshi Sahara echo '</td>'; 268675f74fbSSatoshi Sahara echo '</tr>'; 2692db397b2SSatoshi Sahara 2702db397b2SSatoshi Sahara echo '<tr class="actions">'; 2712db397b2SSatoshi Sahara echo '<td>'; 272*dd9e8e5eSAndreas Gohr media_preview_buttons($this->id, $auth, $rev1); 2732db397b2SSatoshi Sahara echo '</td>'; 2742db397b2SSatoshi Sahara 2752db397b2SSatoshi Sahara echo '<td>'; 2766714d8ceSSatoshi Sahara media_preview_buttons($this->id, $auth, $rev2); 2772db397b2SSatoshi Sahara echo '</td>'; 278675f74fbSSatoshi Sahara echo '</tr>'; 2792db397b2SSatoshi Sahara 2806714d8ceSSatoshi Sahara $rev1Tags = media_file_tags($rev1Meta); 2816714d8ceSSatoshi Sahara $rev2Tags = media_file_tags($rev2Meta); 2826714d8ceSSatoshi Sahara // FIXME rev2Tags-only stuff ignored 2836714d8ceSSatoshi Sahara foreach ($rev1Tags as $key => $tag) { 2846714d8ceSSatoshi Sahara if ($tag['value'] != $rev2Tags[$key]['value']) { 2856714d8ceSSatoshi Sahara $rev2Tags[$key]['highlighted'] = true; 2866714d8ceSSatoshi Sahara $rev1Tags[$key]['highlighted'] = true; 2876714d8ceSSatoshi Sahara } elseif (!$tag['value'] || !$rev2Tags[$key]['value']) { 2886714d8ceSSatoshi Sahara unset($rev2Tags[$key]); 2896714d8ceSSatoshi Sahara unset($rev1Tags[$key]); 2902db397b2SSatoshi Sahara } 2912db397b2SSatoshi Sahara } 2922db397b2SSatoshi Sahara 2932db397b2SSatoshi Sahara echo '<tr>'; 2946714d8ceSSatoshi Sahara foreach ([$rev1Tags, $rev2Tags] as $tags) { 295675f74fbSSatoshi Sahara echo '<td>'; 2962db397b2SSatoshi Sahara 2972db397b2SSatoshi Sahara echo '<dl class="img_tags">'; 2982db397b2SSatoshi Sahara foreach ($tags as $tag) { 2992db397b2SSatoshi Sahara $value = cleanText($tag['value']); 3002db397b2SSatoshi Sahara if (!$value) $value = '-'; 3012db397b2SSatoshi Sahara echo '<dt>' . $lang[$tag['tag'][1]] . '</dt>'; 3022db397b2SSatoshi Sahara echo '<dd>'; 303f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '<strong>'; 3042db397b2SSatoshi Sahara if ($tag['tag'][2] == 'date') { 3052db397b2SSatoshi Sahara echo dformat($value); 3062db397b2SSatoshi Sahara } else { 3072db397b2SSatoshi Sahara echo hsc($value); 3082db397b2SSatoshi Sahara } 309f2749649SSatoshi Sahara if (!empty($tag['highlighted'])) echo '</strong>'; 3102db397b2SSatoshi Sahara echo '</dd>'; 3112db397b2SSatoshi Sahara } 312675f74fbSSatoshi Sahara echo '</dl>'; 3132db397b2SSatoshi Sahara 3142db397b2SSatoshi Sahara echo '</td>'; 3152db397b2SSatoshi Sahara } 316675f74fbSSatoshi Sahara echo '</tr>'; 3172db397b2SSatoshi Sahara 318675f74fbSSatoshi Sahara echo '</table>'; 319675f74fbSSatoshi Sahara echo '</div>'; 32063ab9afeSSatoshi Sahara } 32163ab9afeSSatoshi Sahara} 322