xref: /dokuwiki/inc/Ui/MediaDiff.php (revision 3712ae9ece92ba7d04a5a39f42b55a84bd64fdef)
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 */
226714d8ceSSatoshi Sahara    protected $Rev1;
236714d8ceSSatoshi Sahara    /* @var RevisionInfo newer revision */
246714d8ceSSatoshi Sahara    protected $Rev2;
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
806714d8ceSSatoshi Sahara        // Rev1 : older, left side
816714d8ceSSatoshi Sahara        // Rev2 : newer, right side
826714d8ceSSatoshi Sahara        $this->Rev1 = new RevisionInfo($changelog->getRevisionInfo($this->rev1));
836714d8ceSSatoshi Sahara        $this->Rev2 = new RevisionInfo($changelog->getRevisionInfo($this->rev2));
846714d8ceSSatoshi Sahara        [$Rev1, $Rev2] = [$this->Rev1, $this->Rev2];
850ea1f71bSSatoshi Sahara
860ea1f71bSSatoshi Sahara        $this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
870ea1f71bSSatoshi Sahara
886714d8ceSSatoshi Sahara        foreach ([$Rev1, $Rev2] as $Revision) {
896714d8ceSSatoshi Sahara            $isCurrent = $changelog->isCurrentRevision($Revision->val('date'));
906714d8ceSSatoshi Sahara            $Revision->isCurrent($isCurrent);
910ea1f71bSSatoshi Sahara
920ea1f71bSSatoshi Sahara            if ($this->is_img) {
936714d8ceSSatoshi Sahara                $rev = $isCurrent ? '' : $Revision->val('date');
940ea1f71bSSatoshi Sahara                $meta = new JpegMeta(mediaFN($this->id, $rev));
950ea1f71bSSatoshi Sahara                // get image width and height for the media manager preview panel
966714d8ceSSatoshi Sahara                $Revision->append([
976714d8ceSSatoshi Sahara                    'previewSize' => media_image_preview_size($this->id, $rev, $meta)
986714d8ceSSatoshi Sahara                ]);
990ea1f71bSSatoshi Sahara            }
1000ea1f71bSSatoshi Sahara        }
1010ea1f71bSSatoshi Sahara
1020ea1f71bSSatoshi Sahara        // re-check image, ensure minimum image width for showImageDiff()
1030ea1f71bSSatoshi Sahara        $this->is_img = ($this->is_img
1046714d8ceSSatoshi Sahara            && ($Rev1->val('previewSize')[0] ?? 0) >= 30
1056714d8ceSSatoshi Sahara            && ($Rev2->val('previewSize')[0] ?? 0) >= 30
1060ea1f71bSSatoshi Sahara        );
1070ea1f71bSSatoshi Sahara        // adjust requested diff view type
1080ea1f71bSSatoshi Sahara        if (!$this->is_img) {
1090ea1f71bSSatoshi Sahara            $this->preference['difftype'] = 'both';
1100ea1f71bSSatoshi Sahara        }
1110ea1f71bSSatoshi Sahara    }
1120ea1f71bSSatoshi Sahara
1130ea1f71bSSatoshi Sahara
1140ea1f71bSSatoshi Sahara    /**
11563ab9afeSSatoshi Sahara     * Shows difference between two revisions of media
116675f74fbSSatoshi Sahara     *
117675f74fbSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
11863ab9afeSSatoshi Sahara     */
119309aaee5SSatoshi Sahara    public function show()
12063ab9afeSSatoshi Sahara    {
121675f74fbSSatoshi Sahara        global $conf;
122675f74fbSSatoshi Sahara
12363ab9afeSSatoshi Sahara        $ns = getNS($this->id);
12463ab9afeSSatoshi Sahara        $auth = auth_quickaclcheck("$ns:*");
125675f74fbSSatoshi Sahara
12679a2d784SGerrit Uitslag        if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return;
127675f74fbSSatoshi Sahara
1280ea1f71bSSatoshi Sahara        // retrieve form parameters: rev, rev2, difftype
1290ea1f71bSSatoshi Sahara        $this->handle();
1300ea1f71bSSatoshi Sahara        // prepare revision info of comparison pair
1310ea1f71bSSatoshi Sahara        $this->preProcess();
132675f74fbSSatoshi Sahara
133675f74fbSSatoshi Sahara        // display intro
134675f74fbSSatoshi Sahara        if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
135675f74fbSSatoshi Sahara
136675f74fbSSatoshi Sahara        // print form to choose diff view type
1370ea1f71bSSatoshi Sahara        if ($this->is_img && !$this->preference['fromAjax']) {
13891e70b5fSSatoshi Sahara            $this->showDiffViewSelector();
139675f74fbSSatoshi Sahara            echo '<div id="mediamanager__diff" >';
140675f74fbSSatoshi Sahara        }
141675f74fbSSatoshi Sahara
142309aaee5SSatoshi Sahara        switch ($this->preference['difftype']) {
143675f74fbSSatoshi Sahara            case 'opacity':
144675f74fbSSatoshi Sahara            case 'portions':
1450ea1f71bSSatoshi Sahara                $this->showImageDiff();
146675f74fbSSatoshi Sahara                break;
147675f74fbSSatoshi Sahara            case 'both':
148675f74fbSSatoshi Sahara            default:
1490ea1f71bSSatoshi Sahara                $this->showFileDiff();
150675f74fbSSatoshi Sahara                break;
151675f74fbSSatoshi Sahara        }
152675f74fbSSatoshi Sahara
1530ea1f71bSSatoshi Sahara        if ($this->is_img && !$this->preference['fromAjax']) {
154675f74fbSSatoshi Sahara            echo '</div>';
155675f74fbSSatoshi Sahara        }
1562db397b2SSatoshi Sahara    }
1572db397b2SSatoshi Sahara
1582db397b2SSatoshi Sahara    /**
159675f74fbSSatoshi Sahara     * Print form to choose diff view type
160675f74fbSSatoshi Sahara     * the dropdown is to be added through JavaScript, see lib/scripts/media.js
1612db397b2SSatoshi Sahara     */
16291e70b5fSSatoshi Sahara    protected function showDiffViewSelector()
1632db397b2SSatoshi Sahara    {
1646714d8ceSSatoshi Sahara        // revision information object
1656714d8ceSSatoshi Sahara        [$Rev1, $Rev2] = [$this->Rev1, $this->Rev2];
1660ea1f71bSSatoshi Sahara
16791e70b5fSSatoshi Sahara        echo '<div class="diffoptions group">';
16891e70b5fSSatoshi Sahara
1692db397b2SSatoshi Sahara        $form = new Form([
1702db397b2SSatoshi Sahara            'id' => 'mediamanager__form_diffview',
1712db397b2SSatoshi Sahara            'action' => media_managerURL([], '&'),
1722db397b2SSatoshi Sahara            'method' => 'get',
1732db397b2SSatoshi Sahara            'class' => 'diffView',
1742db397b2SSatoshi Sahara        ]);
1752db397b2SSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
1762db397b2SSatoshi Sahara        $form->setHiddenField('sectok', null);
1772db397b2SSatoshi Sahara        $form->setHiddenField('mediado', 'diff');
1786714d8ceSSatoshi Sahara        $form->setHiddenField('rev2[0]', (int)$Rev1->val('date'));
1796714d8ceSSatoshi Sahara        $form->setHiddenField('rev2[1]', (int)$Rev2->val('date'));
1802db397b2SSatoshi Sahara        $form->addTagClose('div');
1812db397b2SSatoshi Sahara        echo $form->toHTML();
18291e70b5fSSatoshi Sahara
18391e70b5fSSatoshi Sahara        echo '</div>'; // .diffoptions
1842db397b2SSatoshi Sahara    }
1852db397b2SSatoshi Sahara
186675f74fbSSatoshi Sahara    /**
187675f74fbSSatoshi Sahara     * Prints two images side by side
188675f74fbSSatoshi Sahara     * and slider
189675f74fbSSatoshi Sahara     *
190675f74fbSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
191675f74fbSSatoshi Sahara     */
1920ea1f71bSSatoshi Sahara    protected function showImageDiff()
193675f74fbSSatoshi Sahara    {
1946714d8ceSSatoshi Sahara        // revision information object
1956714d8ceSSatoshi Sahara        [$Rev1, $Rev2] = [$this->Rev1, $this->Rev2];
1966714d8ceSSatoshi Sahara
1976714d8ceSSatoshi Sahara        $rev1 = $Rev1->isCurrent() ? '' : $Rev1->val('date');
1986714d8ceSSatoshi Sahara        $rev2 = $Rev2->isCurrent() ? '' : $Rev2->val('date');
1996714d8ceSSatoshi Sahara
2000ea1f71bSSatoshi Sahara        // diff view type: opacity or portions
201675f74fbSSatoshi Sahara        $type = $this->preference['difftype'];
2020ea1f71bSSatoshi Sahara
203675f74fbSSatoshi Sahara        // adjust image width, right side (newer) has priority
2046714d8ceSSatoshi Sahara        $rev1Size = $Rev1->val('previewSize');
2056714d8ceSSatoshi Sahara        $rev2Size = $Rev2->val('previewSize');
2066714d8ceSSatoshi Sahara        if ($rev1Size != $rev2Size) {
2076714d8ceSSatoshi Sahara            if ($rev2Size[0] > $rev1Size[0]) {
2086714d8ceSSatoshi Sahara                $rev1Size = $rev2Size;
2092db397b2SSatoshi Sahara            }
2102db397b2SSatoshi Sahara        }
2112db397b2SSatoshi Sahara
2126714d8ceSSatoshi Sahara        $rev1Src = ml($this->id, ['rev' => $rev1, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
2136714d8ceSSatoshi Sahara        $rev2Src = ml($this->id, ['rev' => $rev2, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
214675f74fbSSatoshi Sahara
215675f74fbSSatoshi Sahara        // slider
2166714d8ceSSatoshi Sahara        echo '<div class="slider" style="max-width: '.($rev1Size[0]-20).'px;" ></div>';
217675f74fbSSatoshi Sahara
218675f74fbSSatoshi Sahara        // two images in divs
219675f74fbSSatoshi Sahara        echo '<div class="imageDiff '.$type.'">';
2206714d8ceSSatoshi Sahara        echo '<div class="image1" style="max-width: '.$rev1Size[0].'px;">';
2216714d8ceSSatoshi Sahara        echo '<img src="'.$rev1Src.'" alt="" />';
222675f74fbSSatoshi Sahara        echo '</div>';
2236714d8ceSSatoshi Sahara        echo '<div class="image2" style="max-width: '.$rev1Size[0].'px;">';
2246714d8ceSSatoshi Sahara        echo '<img src="'.$rev2Src.'" 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
2416714d8ceSSatoshi Sahara        // revision information object
2426714d8ceSSatoshi Sahara        [$Rev1, $Rev2] = [$this->Rev1, $this->Rev2];
2430ea1f71bSSatoshi Sahara
2446714d8ceSSatoshi Sahara        $rev1 = $Rev1->isCurrent() ? '' : (int)$Rev1->val('date');
2456714d8ceSSatoshi Sahara        $rev2 = $Rev2->isCurrent() ? '' : (int)$Rev2->val('date');
2466714d8ceSSatoshi Sahara
2476714d8ceSSatoshi Sahara        // revision title
2486714d8ceSSatoshi Sahara        $rev1Title = trim($Rev1->showRevisionTitle() .' '. $Rev1->showCurrentIndicator());
249*3712ae9eSSatoshi Sahara        $rev1Summary = ($Rev1->val('date'))
2506714d8ceSSatoshi Sahara            ? $Rev1->showEditSummary() .' '. $Rev1->showEditor()
2516714d8ceSSatoshi Sahara            : '';
2526714d8ceSSatoshi Sahara        $rev2Title = trim($Rev2->showRevisionTitle() .' '. $Rev2->showCurrentIndicator());
253*3712ae9eSSatoshi Sahara        $rev2Summary = ($Rev2->val('date'))
2546714d8ceSSatoshi Sahara            ? $Rev2->showEditSummary() .' '. $Rev2->showEditor()
2556714d8ceSSatoshi Sahara            : '';
2566714d8ceSSatoshi Sahara
2576714d8ceSSatoshi Sahara        $rev1Meta = new JpegMeta(mediaFN($this->id, $rev1));
2586714d8ceSSatoshi Sahara        $rev2Meta = new JpegMeta(mediaFN($this->id, $rev2));
2592db397b2SSatoshi Sahara
260179b4660SSatoshi Sahara        // display diff view table
2612db397b2SSatoshi Sahara        echo '<div class="table">';
2622db397b2SSatoshi Sahara        echo '<table>';
2632db397b2SSatoshi Sahara        echo '<tr>';
264*3712ae9eSSatoshi Sahara        echo '<th>'. $rev1Title .' '. $rev1Summary .'</th>';
265*3712ae9eSSatoshi Sahara        echo '<th>'. $rev2Title .' '. $rev2Summary .'</th>';
266675f74fbSSatoshi Sahara        echo '</tr>';
2672db397b2SSatoshi Sahara
2682db397b2SSatoshi Sahara        echo '<tr class="image">';
2692db397b2SSatoshi Sahara        echo '<td>';
2706714d8ceSSatoshi Sahara        media_preview($this->id, $auth, $rev1, $rev1Meta); // $auth not used in media_preview()?
2712db397b2SSatoshi Sahara        echo '</td>';
2722db397b2SSatoshi Sahara
2732db397b2SSatoshi Sahara        echo '<td>';
2746714d8ceSSatoshi Sahara        media_preview($this->id, $auth, $rev2, $rev2Meta);
2752db397b2SSatoshi Sahara        echo '</td>';
276675f74fbSSatoshi Sahara        echo '</tr>';
2772db397b2SSatoshi Sahara
2782db397b2SSatoshi Sahara        echo '<tr class="actions">';
2792db397b2SSatoshi Sahara        echo '<td>';
2806714d8ceSSatoshi Sahara        media_preview_buttons($this->id, $auth, $rev1); // $auth used in media_preview_buttons()
2812db397b2SSatoshi Sahara        echo '</td>';
2822db397b2SSatoshi Sahara
2832db397b2SSatoshi Sahara        echo '<td>';
2846714d8ceSSatoshi Sahara        media_preview_buttons($this->id, $auth, $rev2);
2852db397b2SSatoshi Sahara        echo '</td>';
286675f74fbSSatoshi Sahara        echo '</tr>';
2872db397b2SSatoshi Sahara
2886714d8ceSSatoshi Sahara        $rev1Tags = media_file_tags($rev1Meta);
2896714d8ceSSatoshi Sahara        $rev2Tags = media_file_tags($rev2Meta);
2906714d8ceSSatoshi Sahara        // FIXME rev2Tags-only stuff ignored
2916714d8ceSSatoshi Sahara        foreach ($rev1Tags as $key => $tag) {
2926714d8ceSSatoshi Sahara            if ($tag['value'] != $rev2Tags[$key]['value']) {
2936714d8ceSSatoshi Sahara                $rev2Tags[$key]['highlighted'] = true;
2946714d8ceSSatoshi Sahara                $rev1Tags[$key]['highlighted'] = true;
2956714d8ceSSatoshi Sahara            } elseif (!$tag['value'] || !$rev2Tags[$key]['value']) {
2966714d8ceSSatoshi Sahara                unset($rev2Tags[$key]);
2976714d8ceSSatoshi Sahara                unset($rev1Tags[$key]);
2982db397b2SSatoshi Sahara            }
2992db397b2SSatoshi Sahara        }
3002db397b2SSatoshi Sahara
3012db397b2SSatoshi Sahara        echo '<tr>';
3026714d8ceSSatoshi Sahara        foreach ([$rev1Tags, $rev2Tags] as $tags) {
303675f74fbSSatoshi Sahara            echo '<td>';
3042db397b2SSatoshi Sahara
3052db397b2SSatoshi Sahara            echo '<dl class="img_tags">';
3062db397b2SSatoshi Sahara            foreach ($tags as $tag) {
3072db397b2SSatoshi Sahara                $value = cleanText($tag['value']);
3082db397b2SSatoshi Sahara                if (!$value) $value = '-';
3092db397b2SSatoshi Sahara                echo '<dt>'.$lang[$tag['tag'][1]].'</dt>';
3102db397b2SSatoshi Sahara                echo '<dd>';
311f2749649SSatoshi Sahara                if (!empty($tag['highlighted'])) echo '<strong>';
3122db397b2SSatoshi Sahara                if ($tag['tag'][2] == 'date') {
3132db397b2SSatoshi Sahara                    echo dformat($value);
3142db397b2SSatoshi Sahara                } else {
3152db397b2SSatoshi Sahara                    echo hsc($value);
3162db397b2SSatoshi Sahara                }
317f2749649SSatoshi Sahara                if (!empty($tag['highlighted'])) echo '</strong>';
3182db397b2SSatoshi Sahara                echo '</dd>';
3192db397b2SSatoshi Sahara            }
320675f74fbSSatoshi Sahara            echo '</dl>';
3212db397b2SSatoshi Sahara
3222db397b2SSatoshi Sahara            echo '</td>';
3232db397b2SSatoshi Sahara        }
324675f74fbSSatoshi Sahara        echo '</tr>';
3252db397b2SSatoshi Sahara
326675f74fbSSatoshi Sahara        echo '</table>';
327675f74fbSSatoshi Sahara        echo '</div>';
32863ab9afeSSatoshi Sahara    }
32963ab9afeSSatoshi Sahara
33063ab9afeSSatoshi Sahara}
331