xref: /dokuwiki/inc/Ui/MediaDiff.php (revision b4b4c5c6c38c48d0726b1826ed7cafa45d7c8134)
163ab9afeSSatoshi Sahara<?php
263ab9afeSSatoshi Sahara
363ab9afeSSatoshi Saharanamespace dokuwiki\Ui;
463ab9afeSSatoshi Sahara
563ab9afeSSatoshi Saharause dokuwiki\ChangeLog\MediaChangeLog;
663ab9afeSSatoshi Saharause dokuwiki\Extension\Event;
763ab9afeSSatoshi Saharause dokuwiki\Form\Form;
863ab9afeSSatoshi Sahara
963ab9afeSSatoshi Sahara/**
1063ab9afeSSatoshi Sahara * DokuWiki MediaDiff Interface
1163ab9afeSSatoshi Sahara *
1263ab9afeSSatoshi Sahara * @package dokuwiki\Ui
1363ab9afeSSatoshi Sahara */
1463ab9afeSSatoshi Saharaclass MediaDiff extends Diff
1563ab9afeSSatoshi Sahara{
1663ab9afeSSatoshi Sahara    /**
1763ab9afeSSatoshi Sahara     * MediaDiff Ui constructor
1863ab9afeSSatoshi Sahara     *
19edb50e6aSSatoshi Sahara     * @param string $id  media id
2063ab9afeSSatoshi Sahara     */
21edb50e6aSSatoshi Sahara    public function __construct($id)
2263ab9afeSSatoshi Sahara    {
2363ab9afeSSatoshi Sahara        $this->id = $id;
24edb50e6aSSatoshi Sahara
25edb50e6aSSatoshi Sahara        $this->preference['fromAjax'] = false; // see doluwiki\Ajax::callMediadiff()
26edb50e6aSSatoshi Sahara        $this->preference['showIntro'] = false;
27675f74fbSSatoshi Sahara        $this->preference['difftype'] = null;  // both, opacity or portions.
2863ab9afeSSatoshi Sahara    }
2963ab9afeSSatoshi Sahara
30*b4b4c5c6SSatoshi Sahara    /** @inheritdoc */
31*b4b4c5c6SSatoshi Sahara    protected function preProcess()
32*b4b4c5c6SSatoshi Sahara    {
33*b4b4c5c6SSatoshi Sahara        parent::preProcess();
34*b4b4c5c6SSatoshi Sahara        if (!isset($this->old_rev, $this->new_rev)) {
35*b4b4c5c6SSatoshi Sahara            // no revision was given, compare previous to current
36*b4b4c5c6SSatoshi Sahara            $changelog = new MediaChangeLog($this->id);
37*b4b4c5c6SSatoshi Sahara            $revs = $changelog->getRevisions(0, 1);
38*b4b4c5c6SSatoshi Sahara            $this->old_rev = file_exists(mediaFN($this->id, $revs[0])) ? $revs[0] : '';
39*b4b4c5c6SSatoshi Sahara            $this->new_rev = '';
40*b4b4c5c6SSatoshi Sahara        }
41*b4b4c5c6SSatoshi Sahara    }
42*b4b4c5c6SSatoshi Sahara
4363ab9afeSSatoshi Sahara    /**
4463ab9afeSSatoshi Sahara     * Shows difference between two revisions of media
45675f74fbSSatoshi Sahara     *
46675f74fbSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
47675f74fbSSatoshi Sahara     * @param string $difftype diff view type for media (both, opacity or portions)
4863ab9afeSSatoshi Sahara     */
49675f74fbSSatoshi Sahara    public function show($difftype = null)
5063ab9afeSSatoshi Sahara    {
51675f74fbSSatoshi Sahara        global $conf;
52675f74fbSSatoshi Sahara
5363ab9afeSSatoshi Sahara        $ns = getNS($this->id);
5463ab9afeSSatoshi Sahara        $auth = auth_quickaclcheck("$ns:*");
55675f74fbSSatoshi Sahara
56675f74fbSSatoshi Sahara        if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return '';
57675f74fbSSatoshi Sahara
58675f74fbSSatoshi Sahara       // determine left and right revision
59*b4b4c5c6SSatoshi Sahara        $this->preProcess();
60*b4b4c5c6SSatoshi Sahara        [$l_rev, $r_rev] = [$this->old_rev, $this->new_rev];
61675f74fbSSatoshi Sahara
62675f74fbSSatoshi Sahara        // prepare event data
63675f74fbSSatoshi Sahara        // NOTE: MEDIA_DIFF event does not found in DokuWiki Event List?
64675f74fbSSatoshi Sahara        $data = array();
65675f74fbSSatoshi Sahara        $data[0] = $this->id;
66675f74fbSSatoshi Sahara        $data[1] = $l_rev;
67675f74fbSSatoshi Sahara        $data[2] = $r_rev;
68675f74fbSSatoshi Sahara        $data[3] = $ns;
69675f74fbSSatoshi Sahara        $data[4] = $auth; // permission level
70675f74fbSSatoshi Sahara        $data[5] = $this->preference['fromAjax'];
71675f74fbSSatoshi Sahara
72675f74fbSSatoshi Sahara        // trigger event
73675f74fbSSatoshi Sahara        Event::createAndTrigger('MEDIA_DIFF', $data, null, false);
74675f74fbSSatoshi Sahara
75675f74fbSSatoshi Sahara        if (is_array($data) && count($data) === 6) {
76675f74fbSSatoshi Sahara            $this->id = $data[0];
77675f74fbSSatoshi Sahara            $l_rev = $data[1];
78675f74fbSSatoshi Sahara            $r_rev = $data[2];
79675f74fbSSatoshi Sahara            $ns    = $data[3];
80675f74fbSSatoshi Sahara            $auth  = $data[4];
81675f74fbSSatoshi Sahara            $this->preference['fromAjax'] = $data[5];
82675f74fbSSatoshi Sahara        } else {
83675f74fbSSatoshi Sahara            return '';
84675f74fbSSatoshi Sahara        }
85675f74fbSSatoshi Sahara
86675f74fbSSatoshi Sahara        $l_meta = new \JpegMeta(mediaFN($this->id, $l_rev));
87675f74fbSSatoshi Sahara        $r_meta = new \JpegMeta(mediaFN($this->id, $r_rev));
88675f74fbSSatoshi Sahara
89675f74fbSSatoshi Sahara        $is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
90675f74fbSSatoshi Sahara        if ($is_img) {
91675f74fbSSatoshi Sahara            // get image width and height for the mediamanager preview panel
92675f74fbSSatoshi Sahara            $l_size = media_image_preview_size($this->id, $l_rev, $l_meta);
93675f74fbSSatoshi Sahara            $r_size = media_image_preview_size($this->id, $r_rev, $r_meta);
94675f74fbSSatoshi Sahara            // re-check image, ensure minimum image width for showImageDiff()
95675f74fbSSatoshi Sahara            $is_img = ($l_size && $r_size && ($l_size[0] >= 30 || $r_size[0] >= 30));
96675f74fbSSatoshi Sahara        }
97675f74fbSSatoshi Sahara
98675f74fbSSatoshi Sahara        // determine requested diff view type
99675f74fbSSatoshi Sahara        $difftype = $this->getDiffType($difftype);
100675f74fbSSatoshi Sahara
101675f74fbSSatoshi Sahara        // display intro
102675f74fbSSatoshi Sahara        if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
103675f74fbSSatoshi Sahara
104675f74fbSSatoshi Sahara        // print form to choose diff view type
105675f74fbSSatoshi Sahara        if ($is_img && !$this->preference['fromAjax']) {
106675f74fbSSatoshi Sahara            $this->showDiffViewSelector($l_rev, $r_rev);
107675f74fbSSatoshi Sahara            echo '<div id="mediamanager__diff" >';
108675f74fbSSatoshi Sahara        }
109675f74fbSSatoshi Sahara
110675f74fbSSatoshi Sahara        if ($is_img) {
111675f74fbSSatoshi Sahara            switch ($difftype) {
112675f74fbSSatoshi Sahara                case 'opacity':
113675f74fbSSatoshi Sahara                case 'portions':
114675f74fbSSatoshi Sahara                    $this->showImageDiff($l_rev, $r_rev, $l_size, $r_size, $difftype);
115675f74fbSSatoshi Sahara                    break;
116675f74fbSSatoshi Sahara                case 'both':
117675f74fbSSatoshi Sahara                default:
118675f74fbSSatoshi Sahara                    $this->showFileDiff($l_rev, $r_rev, $l_meta, $r_meta, $auth);
119675f74fbSSatoshi Sahara                    break;
120675f74fbSSatoshi Sahara            }
121675f74fbSSatoshi Sahara        } else {
122675f74fbSSatoshi Sahara            $this->showFileDiff($l_rev, $r_rev, $l_meta, $r_meta, $auth);
123675f74fbSSatoshi Sahara        }
124675f74fbSSatoshi Sahara
125675f74fbSSatoshi Sahara        if ($is_img && !$this->preference['fromAjax']) {
126675f74fbSSatoshi Sahara            echo '</div>';
127675f74fbSSatoshi Sahara        }
1282db397b2SSatoshi Sahara    }
1292db397b2SSatoshi Sahara
1302db397b2SSatoshi Sahara    /**
131675f74fbSSatoshi Sahara     * Determine requested diff view type for media
1322db397b2SSatoshi Sahara     *
133675f74fbSSatoshi Sahara     * @param string $mode  diff view type (both, opacity or portions)
134675f74fbSSatoshi Sahara     * @return string
1352db397b2SSatoshi Sahara     */
136675f74fbSSatoshi Sahara    protected function getDiffType($mode = null)
1372db397b2SSatoshi Sahara    {
1382db397b2SSatoshi Sahara        global $INPUT;
139675f74fbSSatoshi Sahara        $difftype =& $this->preference['difftype'];
1402db397b2SSatoshi Sahara
141675f74fbSSatoshi Sahara        if (!isset($mode)) {
142675f74fbSSatoshi Sahara            $difftype = $INPUT->str('difftype');
143675f74fbSSatoshi Sahara        } elseif (in_array($mode, ['both', 'opacity', 'portions'])) {
144675f74fbSSatoshi Sahara            $difftype = $mode;
145675f74fbSSatoshi Sahara        }
146675f74fbSSatoshi Sahara        return $this->preference['difftype'];
147675f74fbSSatoshi Sahara    }
148675f74fbSSatoshi Sahara
149675f74fbSSatoshi 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     *
153675f74fbSSatoshi Sahara     * @param int $l_rev  revision timestamp of left side
154675f74fbSSatoshi Sahara     * @param int $r_rev  revision timestamp of right side
1552db397b2SSatoshi Sahara     */
156675f74fbSSatoshi Sahara    protected function showDiffViewSelector($l_rev, $r_rev)
1572db397b2SSatoshi Sahara    {
1582db397b2SSatoshi Sahara        $form = new Form([
1592db397b2SSatoshi Sahara            'id' => 'mediamanager__form_diffview',
1602db397b2SSatoshi Sahara            'action' => media_managerURL([], '&'),
1612db397b2SSatoshi Sahara            'method' => 'get',
1622db397b2SSatoshi Sahara            'class' => 'diffView',
1632db397b2SSatoshi Sahara        ]);
1642db397b2SSatoshi Sahara        $form->addTagOpen('div')->addClass('no');
1652db397b2SSatoshi Sahara        $form->setHiddenField('sectok', null);
1662db397b2SSatoshi Sahara        $form->setHiddenField('mediado', 'diff');
1672db397b2SSatoshi Sahara        $form->setHiddenField('rev2[0]', $l_rev);
1682db397b2SSatoshi Sahara        $form->setHiddenField('rev2[1]', $r_rev);
1692db397b2SSatoshi Sahara        $form->addTagClose('div');
1702db397b2SSatoshi Sahara        echo $form->toHTML();
1712db397b2SSatoshi Sahara    }
1722db397b2SSatoshi Sahara
173675f74fbSSatoshi Sahara    /**
174675f74fbSSatoshi Sahara     * Prints two images side by side
175675f74fbSSatoshi Sahara     * and slider
176675f74fbSSatoshi Sahara     *
177675f74fbSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
178675f74fbSSatoshi Sahara     *
179675f74fbSSatoshi Sahara     * @param int    $l_rev   revision timestamp, or empty string
180675f74fbSSatoshi Sahara     * @param int    $r_rev   revision timestamp, or empty string
181675f74fbSSatoshi Sahara     * @param array  $l_size  array with width and height
182675f74fbSSatoshi Sahara     * @param array  $r_size  array with width and height
183675f74fbSSatoshi Sahara     * @param string $type    diff type: opacity or portions
184675f74fbSSatoshi Sahara     */
185675f74fbSSatoshi Sahara    protected function showImageDiff($l_rev, $r_rev, $l_size, $r_size, $type = null)
186675f74fbSSatoshi Sahara    {
187675f74fbSSatoshi Sahara        if (!isset($type)) {
188675f74fbSSatoshi Sahara            $type = $this->preference['difftype'];
189675f74fbSSatoshi Sahara        }
190675f74fbSSatoshi Sahara
191675f74fbSSatoshi Sahara        // adjust image width, right side (newer) has priority
192675f74fbSSatoshi Sahara        if ($l_size != $r_size) {
193675f74fbSSatoshi Sahara            if ($r_size[0] > $l_size[0]) {
194675f74fbSSatoshi Sahara                $l_size = $r_size;
1952db397b2SSatoshi Sahara            }
1962db397b2SSatoshi Sahara        }
1972db397b2SSatoshi Sahara
198675f74fbSSatoshi Sahara        $l_src = ml($this->id, ['rev' => $l_rev, 'h' => $l_size[1], 'w' => $l_size[0]]);
199675f74fbSSatoshi Sahara        $r_src = ml($this->id, ['rev' => $r_rev, 'h' => $l_size[1], 'w' => $l_size[0]]);
200675f74fbSSatoshi Sahara
201675f74fbSSatoshi Sahara        // slider
202675f74fbSSatoshi Sahara        echo '<div class="slider" style="max-width: '.($l_size[0]-20).'px;" ></div>';
203675f74fbSSatoshi Sahara
204675f74fbSSatoshi Sahara        // two images in divs
205675f74fbSSatoshi Sahara        echo '<div class="imageDiff '.$type.'">';
206675f74fbSSatoshi Sahara        echo '<div class="image1" style="max-width: '.$l_size[0].'px;">';
207675f74fbSSatoshi Sahara        echo '<img src="'.$l_src.'" alt="" />';
208675f74fbSSatoshi Sahara        echo '</div>';
209675f74fbSSatoshi Sahara        echo '<div class="image2" style="max-width: '.$l_size[0].'px;">';
210675f74fbSSatoshi Sahara        echo '<img src="'.$r_src.'" alt="" />';
211675f74fbSSatoshi Sahara        echo '</div>';
212675f74fbSSatoshi Sahara        echo '</div>';
213675f74fbSSatoshi Sahara    }
214675f74fbSSatoshi Sahara
215675f74fbSSatoshi Sahara    /**
216675f74fbSSatoshi Sahara     * Shows difference between two revisions of media file
217675f74fbSSatoshi Sahara     *
218675f74fbSSatoshi Sahara     * @author Kate Arzamastseva <pshns@ukr.net>
219675f74fbSSatoshi Sahara     *
220675f74fbSSatoshi Sahara     * @param string|int $l_rev revision timestamp, or empty string
221675f74fbSSatoshi Sahara     * @param string|int $r_rev revision timestamp, or empty string
222675f74fbSSatoshi Sahara     * @param JpegMeta $l_meta
223675f74fbSSatoshi Sahara     * @param JpegMeta $r_meta
224675f74fbSSatoshi Sahara     * @param int $auth permission level
225675f74fbSSatoshi Sahara     */
226675f74fbSSatoshi Sahara    protected function showFileDiff($l_rev, $r_rev, $l_meta, $r_meta, $auth)
227675f74fbSSatoshi Sahara    {
228675f74fbSSatoshi Sahara        $medialog = new MediaChangeLog($this->id);
2292db397b2SSatoshi Sahara
2302db397b2SSatoshi Sahara        list($l_head, $r_head) = $this->diffHead($medialog, $l_rev, $r_rev);
2312db397b2SSatoshi Sahara
2322db397b2SSatoshi Sahara        echo '<div class="table">';
2332db397b2SSatoshi Sahara        echo '<table>';
2342db397b2SSatoshi Sahara        echo '<tr>';
2352db397b2SSatoshi Sahara        echo '<th>'. $l_head .'</th>';
2362db397b2SSatoshi Sahara        echo '<th>'. $r_head .'</th>';
237675f74fbSSatoshi Sahara        echo '</tr>';
2382db397b2SSatoshi Sahara
2392db397b2SSatoshi Sahara        echo '<tr class="image">';
2402db397b2SSatoshi Sahara        echo '<td>';
241675f74fbSSatoshi Sahara        media_preview($this->id, $auth, $l_rev, $l_meta); // $auth not used in media_preview()?
2422db397b2SSatoshi Sahara        echo '</td>';
2432db397b2SSatoshi Sahara
2442db397b2SSatoshi Sahara        echo '<td>';
245675f74fbSSatoshi Sahara        media_preview($this->id, $auth, $r_rev, $r_meta);
2462db397b2SSatoshi Sahara        echo '</td>';
247675f74fbSSatoshi Sahara        echo '</tr>';
2482db397b2SSatoshi Sahara
2492db397b2SSatoshi Sahara        echo '<tr class="actions">';
2502db397b2SSatoshi Sahara        echo '<td>';
251675f74fbSSatoshi Sahara        media_preview_buttons($this->id, $auth, $l_rev); // $auth used in media_preview_buttons()
2522db397b2SSatoshi Sahara        echo '</td>';
2532db397b2SSatoshi Sahara
2542db397b2SSatoshi Sahara        echo '<td>';
255675f74fbSSatoshi Sahara        media_preview_buttons($this->id, $auth, $r_rev);
2562db397b2SSatoshi Sahara        echo '</td>';
257675f74fbSSatoshi Sahara        echo '</tr>';
2582db397b2SSatoshi Sahara
2592db397b2SSatoshi Sahara        $l_tags = media_file_tags($l_meta);
2602db397b2SSatoshi Sahara        $r_tags = media_file_tags($r_meta);
2612db397b2SSatoshi Sahara        // FIXME r_tags-only stuff
2622db397b2SSatoshi Sahara        foreach ($l_tags as $key => $l_tag) {
2632db397b2SSatoshi Sahara            if ($l_tag['value'] != $r_tags[$key]['value']) {
2642db397b2SSatoshi Sahara                $r_tags[$key]['highlighted'] = true;
2652db397b2SSatoshi Sahara                $l_tags[$key]['highlighted'] = true;
2662db397b2SSatoshi Sahara            } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) {
2672db397b2SSatoshi Sahara                unset($r_tags[$key]);
2682db397b2SSatoshi Sahara                unset($l_tags[$key]);
2692db397b2SSatoshi Sahara            }
2702db397b2SSatoshi Sahara        }
2712db397b2SSatoshi Sahara
2722db397b2SSatoshi Sahara        echo '<tr>';
2732db397b2SSatoshi Sahara        foreach (array($l_tags, $r_tags) as $tags) {
274675f74fbSSatoshi Sahara            echo '<td>';
2752db397b2SSatoshi Sahara
2762db397b2SSatoshi Sahara            echo '<dl class="img_tags">';
2772db397b2SSatoshi Sahara            foreach ($tags as $tag) {
2782db397b2SSatoshi Sahara                $value = cleanText($tag['value']);
2792db397b2SSatoshi Sahara                if (!$value) $value = '-';
2802db397b2SSatoshi Sahara                echo '<dt>'.$lang[$tag['tag'][1]].'</dt>';
2812db397b2SSatoshi Sahara                echo '<dd>';
2822db397b2SSatoshi Sahara                if ($tag['highlighted']) echo '<strong>';
2832db397b2SSatoshi Sahara                if ($tag['tag'][2] == 'date') {
2842db397b2SSatoshi Sahara                    echo dformat($value);
2852db397b2SSatoshi Sahara                } else {
2862db397b2SSatoshi Sahara                    echo hsc($value);
2872db397b2SSatoshi Sahara                }
2882db397b2SSatoshi Sahara                if ($tag['highlighted']) echo '</strong>';
2892db397b2SSatoshi Sahara                echo '</dd>';
2902db397b2SSatoshi Sahara            }
291675f74fbSSatoshi Sahara            echo '</dl>';
2922db397b2SSatoshi Sahara
2932db397b2SSatoshi Sahara            echo '</td>';
2942db397b2SSatoshi Sahara        }
295675f74fbSSatoshi Sahara        echo '</tr>';
2962db397b2SSatoshi Sahara
297675f74fbSSatoshi Sahara        echo '</table>';
298675f74fbSSatoshi Sahara        echo '</div>';
29963ab9afeSSatoshi Sahara    }
30063ab9afeSSatoshi Sahara
30163ab9afeSSatoshi Sahara}
302