Failed Conditions
Pull Request — master (#3361)
by
unknown
03:00
created

MediaDiff::showFileDiff()   C

Complexity

Conditions 11
Paths 72

Size

Total Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 72
nop 5
dl 0
loc 78
rs 6.3333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace dokuwiki\Ui;
4
5
use dokuwiki\ChangeLog\MediaChangeLog;
6
use dokuwiki\Ui\MediaRevisions;
7
use dokuwiki\Extension\Event;
8
use dokuwiki\Form\Form;
9
use JpegMeta;
10
11
/**
12
 * DokuWiki MediaDiff Interface
13
 *
14
 * @package dokuwiki\Ui
15
 */
16
class MediaDiff extends Diff
17
{
18
    /* @var MediaChangeLog */
19
    protected $changelog;
20
21
    /**
22
     * MediaDiff Ui constructor
23
     *
24
     * @param string $id  media id
25
     */
26
    public function __construct($id)
27
    {
28
        if (!isset($id)) {
29
            throw new \InvalidArgumentException('media id should not be empty!');
30
        }
31
        $this->item = 'media';
32
33
        // init preference
34
        $this->preference['fromAjax'] = false; // see doluwiki\Ajax::callMediadiff()
35
        $this->preference['showIntro'] = false;
36
        $this->preference['difftype'] = 'both';  // media diff view type: both, opacity or portions
37
38
        parent::__construct($id);
39
    }
40
41
    /** @inheritdoc */
42
    protected function setChangeLog()
43
    {
44
        $this->changelog = new MediaChangeLog($this->id);
45
    }
46
47
    /** @inheritdoc */
48
    protected function itemFN($id, $rev = '')
49
    {
50
        return mediaFN($id, $rev);
51
    }
52
53
    /** @inheritdoc */
54
    protected function preProcess()
55
    {
56
        parent::preProcess();
57
        if (!isset($this->oldRev, $this->newRev)) {
58
            // no revision was given, compare previous to current
59
            $revs = $this->changelog->getRevisions(0, 1);
60
            $this->oldRev = file_exists(mediaFN($this->id, $revs[0])) ? $revs[0] : '';
61
            $this->newRev = '';
62
        }
63
    }
64
65
    /**
66
     * Shows difference between two revisions of media
67
     *
68
     * @author Kate Arzamastseva <[email protected]>
69
     */
70
    public function show()
71
    {
72
        global $conf;
73
74
        $ns = getNS($this->id);
75
        $auth = auth_quickaclcheck("$ns:*");
76
77
        if ($auth < AUTH_READ || !$this->id || !$conf['mediarevisions']) return '';
78
79
       // determine left and right revision
80
        if (!isset($this->oldRev, $this->newRev)) $this->preProcess();
81
        [$oldRev, $newRev] = [$this->oldRev, $this->newRev];
0 ignored issues
show
Bug introduced by
The variable $oldRev seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
Bug introduced by
The variable $newRev seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
82
83
        // prepare event data
84
        // NOTE: MEDIA_DIFF event does not found in DokuWiki Event List?
85
        $data = array();
86
        $data[0] = $this->id;
87
        $data[1] = $oldRev;
0 ignored issues
show
Bug introduced by
The variable $oldRev seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
88
        $data[2] = $newRev;
0 ignored issues
show
Bug introduced by
The variable $newRev seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
89
        $data[3] = $ns;
90
        $data[4] = $auth; // permission level
91
        $data[5] = $this->preference['fromAjax'];
92
93
        // trigger event
94
        Event::createAndTrigger('MEDIA_DIFF', $data, null, false);
95
96
        if (is_array($data) && count($data) === 6) {
97
            $this->id = $data[0];
98
            $oldRev = $data[1];
99
            $newRev = $data[2];
100
            $ns     = $data[3];
0 ignored issues
show
Unused Code introduced by
$ns is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
101
            $auth   = $data[4];
102
            $this->preference['fromAjax'] = $data[5];
103
        } else {
104
            return '';
105
        }
106
107
        $oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev));
108
        $newRevMeta = new JpegMeta(mediaFN($this->id, $newRev));
109
110
        $is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
111
        if ($is_img) {
112
            // get image width and height for the mediamanager preview panel
113
            $oldRevSize = media_image_preview_size($this->id, $oldRev, $oldRevMeta);
114
            $newRevSize = media_image_preview_size($this->id, $newRev, $newRevMeta);
115
            // re-check image, ensure minimum image width for showImageDiff()
116
            $is_img = ($oldRevSize && $newRevSize && ($oldRevSize[0] >= 30 || $newRevSize[0] >= 30));
0 ignored issues
show
Bug Best Practice introduced by
The expression $oldRevSize of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Bug Best Practice introduced by
The expression $newRevSize of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
117
        }
118
119
        // determine requested diff view type
120
        if (!$is_img) {
121
            $this->preference['difftype'] = 'both';
122
        }
123
124
        // display intro
125
        if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
126
127
        // print form to choose diff view type
128
        if ($is_img && !$this->preference['fromAjax']) {
129
            $this->showDiffViewSelector();
130
            echo '<div id="mediamanager__diff" >';
131
        }
132
133
        switch ($this->preference['difftype']) {
134
            case 'opacity':
135
            case 'portions':
136
                $this->showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize);
0 ignored issues
show
Bug introduced by
The variable $oldRevSize does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $newRevSize does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
137
                break;
138
            case 'both':
139
            default:
140
                $this->showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth);
141
                break;
142
        }
143
144
        if ($is_img && !$this->preference['fromAjax']) {
145
            echo '</div>';
146
        }
147
    }
148
149
    /**
150
     * Print form to choose diff view type
151
     * the dropdown is to be added through JavaScript, see lib/scripts/media.js
152
     */
153
    protected function showDiffViewSelector()
154
    {
155
        echo '<div class="diffoptions group">';
156
157
        $form = new Form([
158
            'id' => 'mediamanager__form_diffview',
159
            'action' => media_managerURL([], '&'),
160
            'method' => 'get',
161
            'class' => 'diffView',
162
        ]);
163
        $form->addTagOpen('div')->addClass('no');
164
        $form->setHiddenField('sectok', null);
165
        $form->setHiddenField('mediado', 'diff');
166
        $form->setHiddenField('rev2[0]', $this->oldRev ?: 'current');
167
        $form->setHiddenField('rev2[1]', $this->newRev ?: 'current');
168
        $form->addTagClose('div');
169
        echo $form->toHTML();
170
171
        echo '</div>'; // .diffoptions
172
    }
173
174
    /**
175
     * Prints two images side by side
176
     * and slider
177
     *
178
     * @author Kate Arzamastseva <[email protected]>
179
     *
180
     * @param string|int $oldRev revision timestamp, or empty string
181
     * @param string|int $newRev revision timestamp, or empty string
182
     * @param array  $oldRevSize  array with width and height
183
     * @param array  $newRevSize  array with width and height
184
     * @param string $type    diff view type: opacity or portions
185
     */
186
    protected function showImageDiff($oldRev, $newRev, $oldRevSize, $newRevSize, $type = null)
187
    {
188
        if (!isset($type)) {
189
            $type = $this->preference['difftype'];
190
        }
191
192
        // adjust image width, right side (newer) has priority
193
        if ($oldRevSize != $newRevSize) {
194
            if ($newRevSize[0] > $oldRevSize[0]) {
195
                $oldRevSize = $newRevSize;
196
            }
197
        }
198
199
        $oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
200
        $newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
201
202
        // slider
203
        echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>';
204
205
        // two images in divs
206
        echo '<div class="imageDiff '.$type.'">';
207
        echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">';
208
        echo '<img src="'.$oldRevSrc.'" alt="" />';
209
        echo '</div>';
210
        echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">';
211
        echo '<img src="'.$newRevSrc.'" alt="" />';
212
        echo '</div>';
213
        echo '</div>';
214
    }
215
216
    /**
217
     * Shows difference between two revisions of media file
218
     *
219
     * @author Kate Arzamastseva <[email protected]>
220
     *
221
     * @param string|int $oldRev revision timestamp, or empty string
222
     * @param string|int $newRev revision timestamp, or empty string
223
     * @param JpegMeta $oldRevMeta
224
     * @param JpegMeta $newRevMeta
225
     * @param int $auth permission level
226
     */
227
    protected function showFileDiff($oldRev, $newRev, $oldRevMeta, $newRevMeta, $auth)
228
    {
229
        global $lang;
230
231
        // revison info of older file (left side)
232
        $oldRevInfo = $this->getExtendedRevisionInfo($oldRev);
233
        // revison info of newer file (right side)
234
        $newRevInfo = $this->getExtendedRevisionInfo($newRev);
235
236
        // display diff view table
237
        echo '<div class="table">';
238
        echo '<table>';
239
        echo '<tr>';
240
        echo '<th>'. $this->revisionTitle($oldRevInfo) .'</th>';
241
        echo '<th>'. $this->revisionTitle($newRevInfo) .'</th>';
242
        echo '</tr>';
243
244
        echo '<tr class="image">';
245
        echo '<td>';
246
        media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()?
247
        echo '</td>';
248
249
        echo '<td>';
250
        media_preview($this->id, $auth, $newRev, $newRevMeta);
251
        echo '</td>';
252
        echo '</tr>';
253
254
        echo '<tr class="actions">';
255
        echo '<td>';
256
        media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons()
257
        echo '</td>';
258
259
        echo '<td>';
260
        media_preview_buttons($this->id, $auth, $newRev);
261
        echo '</td>';
262
        echo '</tr>';
263
264
        $l_tags = media_file_tags($oldRevMeta);
265
        $r_tags = media_file_tags($newRevMeta);
266
        // FIXME r_tags-only stuff
267
        foreach ($l_tags as $key => $l_tag) {
268
            if ($l_tag['value'] != $r_tags[$key]['value']) {
269
                $r_tags[$key]['highlighted'] = true;
270
                $l_tags[$key]['highlighted'] = true;
271
            } elseif (!$l_tag['value'] || !$r_tags[$key]['value']) {
272
                unset($r_tags[$key]);
273
                unset($l_tags[$key]);
274
            }
275
        }
276
277
        echo '<tr>';
278
        foreach (array($l_tags, $r_tags) as $tags) {
279
            echo '<td>';
280
281
            echo '<dl class="img_tags">';
282
            foreach ($tags as $tag) {
283
                $value = cleanText($tag['value']);
284
                if (!$value) $value = '-';
285
                echo '<dt>'.$lang[$tag['tag'][1]].'</dt>';
286
                echo '<dd>';
287
                if ($tag['highlighted']) echo '<strong>';
288
                if ($tag['tag'][2] == 'date') {
289
                    echo dformat($value);
290
                } else {
291
                    echo hsc($value);
292
                }
293
                if ($tag['highlighted']) echo '</strong>';
294
                echo '</dd>';
295
            }
296
            echo '</dl>';
297
298
            echo '</td>';
299
        }
300
        echo '</tr>';
301
302
        echo '</table>';
303
        echo '</div>';
304
    }
305
306
    /**
307
     * Revision Title for MediaDiff table headline
308
     *
309
     * @param array $info  Revision info structure of a media file
310
     * @return string
311
     */
312
    protected function revisionTitle(array $info)
313
    {
314
        global $lang, $INFO;
315
316
        if (isset($info['date'])) {
317
            $rev = $info['date'];
318
            $title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">'
319
                   . dformat($rev).'</a></bdi>';
320
        } else {
321
            $rev = false;
322
            $title = '&mdash;';
323
        }
324
        if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) {
325
            $title .= '&nbsp;('.$lang['current'].')';
326
        }
327
328
        // append separator
329
        $title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
330
331
        // supplement
332
        if (isset($info['date'])) {
333
            $objRevInfo = (new MediaRevisions($this->id))->getObjRevInfo($info);
334
            $title .= $objRevInfo->editSummary().' '.$objRevInfo->editor();
335
        }
336
        return $title;
337
    }
338
339
}
340