Failed Conditions
Pull Request — master (#3198)
by
unknown
03:28
created

Revisions::show()   F

Complexity

Conditions 42
Paths > 20000

Size

Total Lines 274

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 42
nc 290505600
nop 0
dl 0
loc 274
rs 0
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\PageChangeLog;
6
use dokuwiki\ChangeLog\MediaChangeLog;
7
use dokuwiki\Extension\Event;
8
use dokuwiki\Form\Form;
9
10
/**
11
 * DokuWiki Revisions Interface
12
 *
13
 * @package dokuwiki\Ui
14
 */
15
class Revisions extends Ui
16
{
17
    protected $first;
18
    protected $media_id;
19
20
    /** 
21
     * Revisions Ui constructor
22
     *
23
     * @param int $first  skip the first n changelog lines
24
     * @param bool|string $media_id  id of media, or false for current page
25
     */
26
    public function __construct($first = 0, $media_id = false)
27
    {
28
        $this->first    = $first;
29
        $this->media_id = $media_id;
30
    }
31
32
    /**
33
     * Display list of old revisions
34
     *
35
     * @author Andreas Gohr <[email protected]>
36
     * @author Ben Coburn <[email protected]>
37
     * @author Kate Arzamastseva <[email protected]>
38
     *
39
     * @triggers HTML_REVISIONSFORM_OUTPUT
40
     * @return void
41
     */
42
    public function show()
43
    {
44
        global $ID;
45
        global $INFO;
46
        global $conf;
47
        global $lang;
48
49
        $first    = $this->first;
50
        $media_id = $this->media_id;
51
52
        $id = $ID;
53
        if ($media_id) {
54
            $id = $media_id;
55
            $changelog = new MediaChangeLog($id);
56
        } else {
57
            $changelog = new PageChangeLog($id);
58
        }
59
60
        /* we need to get one additional log entry to be able to
61
         * decide if this is the last page or is there another one.
62
         * see html_recent()
63
         */
64
65
        $revisions = $changelog->getRevisions($first, $conf['recent'] +1);
66
67
        if (count($revisions) == 0 && $first != 0) {
68
            $first = 0;
69
            $revisions = $changelog->getRevisions($first, $conf['recent'] +1);
70
        }
71
        $hasNext = false;
72
        if (count($revisions) > $conf['recent']) {
73
            $hasNext = true;
74
            array_pop($revisions); // remove extra log entry
75
        }
76
77
        // print intro
78
        if (!$media_id) {
79
            print p_locale_xhtml('revisions');
80
            $exists = $INFO['exists'];
81
            $display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
82
            if (!$display_name) {
83
                $display_name = $id;
84
            }
85
        } else {
86
            $exists = file_exists(mediaFN($id));
87
            $display_name = $id;
88
        }
89
90
        // create the form
91
        $form = new Form(['id' => 'page__revisions']);
92
        $form->addClass('changes');
93
        if ($media_id) {
94
            $form->attr('action', media_managerURL(array('image' => $media_id), '&'));
0 ignored issues
show
Bug introduced by
It seems like media_managerURL(array('...ge' => $media_id), '&') targeting media_managerURL() can also be of type array; however, dokuwiki\Form\Element::attr() does only seem to accept null|string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
95
        }
96
97
        // start listing
98
        $form->addTagOpen('ul');
99
100
        if ($exists && $first == 0) {
101
            $minor = false;
102
            if ($media_id) {
103
                $date = dformat(@filemtime(mediaFN($id)));
104
                $href = media_managerURL(array('image' => $id, 'tab_details' => 'view'), '&');
105
106
                $changelog->setChunkSize(1024);
107
                $revinfo = $changelog->getRevisionInfo(@filemtime(fullpath(mediaFN($id))));
108
109
                $summary = $revinfo['sum'];
110
                $editor = $revinfo['user'] ?: $revinfo['ip'];
111
                $sizechange = $revinfo['sizechange'];
112
            } else {
113
                $date = dformat($INFO['lastmod']);
114
                if (isset($INFO['meta']) && isset($INFO['meta']['last_change'])) {
115
                    if ($INFO['meta']['last_change']['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) {
116
                        $minor = true;
117
                    }
118
                    if (isset($INFO['meta']['last_change']['sizechange'])) {
119
                        $sizechange = $INFO['meta']['last_change']['sizechange'];
120
                    } else {
121
                        $sizechange = null;
122
                    }
123
                }
124
                $pagelog = new PageChangeLog($ID);
125
                $latestrev = $pagelog->getRevisions(-1, 1);
126
                $latestrev = array_pop($latestrev);
127
                $href = wl($id, "rev=$latestrev", false, '&');
128
                $summary = $INFO['sum'];
129
                $editor = $INFO['editor'];
130
            }
131
132
            $form->addTagOpen('li')->addClass($minor ? 'minor' : '');
133
            $form->addTagOpen('div')->addClass('li');
134
            $form->addCheckbox('rev2[]')->val('current');
135
136
            $form->addTagOpen('span')->addClass('data');
137
            $form->addHTML($date);
138
            $form->addTagClose('span');
139
140
            $form->addTag('img')->attrs([
141
                'src' => DOKU_BASE.'lib/images/blank.gif',
142
                'width' => 15,
143
                'height' => 11,
144
                'alt' => '',
145
            ]);
146
147
            $form->addTagOPen('a')->attr('href', $href)->addClass('wikilink1');
0 ignored issues
show
Bug introduced by
It seems like $href defined by media_managerURL(array('...tails' => 'view'), '&') on line 104 can also be of type array; however, dokuwiki\Form\Element::attr() does only seem to accept null|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
148
            $form->addHTML($display_name);
149
            $form->addTagClose('a');
150
151
            if ($media_id) $form->addTagOpen('div');
152
153
            if ($summary) {
154
                $form->addTagOpen('span')->addClass('sum');
155
                if (!$media_id) $form->addHTML(' – ');
156
                $form->addHTML('<bdi>' . hsc($summary) . '</bdi>');
157
                $form->addTagClose('span');
158
            }
159
160
            $form->addTagOpen('span')->addClass('user');
161
            $form->addHTML(
162
                (empty($editor)) ? ('('.$lang['external_edit'].')') : '<bdi>'.editorinfo($editor).'</bdi>'
163
            );
164
            $form->addTagClose('span');
165
166
167
            html_sizechange($sizechange, $form);
0 ignored issues
show
Bug introduced by
The variable $sizechange 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...
Documentation introduced by
$form is of type object<dokuwiki\Form\Form>, but the function expects a object<Form>|object<Doku_Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
168
169
            $form->addHTML('('.$lang['current'].')');
170
171
            if ($media_id) $form->addTagClose('div');
172
173
            $form->addTagClose('div');
174
            $form->addTagClose('li');
175
        }
176
177
        foreach ($revisions as $rev) {
178
            $date = dformat($rev);
179
            $info = $changelog->getRevisionInfo($rev);
180
            if ($media_id) {
181
                $exists = file_exists(mediaFN($id, $rev));
182
            } else {
183
                $exists = page_exists($id, $rev);
184
            }
185
186
            $class = '';
187
            if ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) {
188
                $class = 'minor';
189
            }
190
191
            $form->addTagOpen('li')->addClass($class);
192
            $form->addTagOpen('div')->addClass('li');
193
194
            if ($exists){
195
                $form->addCheckbox('rev2[]')->val($rev);
196
            } else {
197
                $form->addTag('img')->attrs([
198
                    'src' => DOKU_BASE.'lib/images/blank.gif',
199
                    'width' => 15,
200
                    'height' => 11,
201
                    'alt' => '',
202
                ]);
203
            }
204
205
            $form->addTagOpen('span')->addClass('date');
206
            $form->addHTML($date);
207
            $form->addTagClose('span');
208
209
            if ($exists) {
210
                if (!$media_id) {
211
                    $href = wl($id, "rev=$rev,do=diff", false, '&');
212
                } else {
213
                    $href = media_managerURL(array('image' => $id, 'rev' => $rev, 'mediado' => 'diff'), '&');
214
                }
215
                $form->addTagOpen('a')->attr('href', $href)->addClass('diff_link');
0 ignored issues
show
Bug introduced by
It seems like $href defined by media_managerURL(array('...diado' => 'diff'), '&') on line 213 can also be of type array; however, dokuwiki\Form\Element::attr() does only seem to accept null|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
216
                $form->addTag('img')->attrs([
217
                    'src'    => DOKU_BASE.'lib/images/diff.png',
218
                    'width'  => 15,
219
                    'height' => 11,
220
                    'title'  => $lang['diff'],
221
                    'alt'    => $lang['diff'],
222
                ]);
223
                $form->addTagClose('a');
224
225
                if (!$media_id) {
226
                    $href = wl($id, "rev=$rev", false, '&');
227
                } else {
228
                    $href = media_managerURL(array('image' => $id, 'tab_details' => 'view', 'rev' => $rev), '&');
229
                }
230
                $form->addTagOpen('a')->attr('href', $href)->addClass('wikilink1');
0 ignored issues
show
Bug introduced by
It seems like $href defined by media_managerURL(array('...', 'rev' => $rev), '&') on line 228 can also be of type array; however, dokuwiki\Form\Element::attr() does only seem to accept null|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
231
                $form->addHTML($display_name);
232
                $form->addTagClose('a');
233
            } else {
234
                $form->addTag('img')->attrs([
235
                    'src'    => DOKU_BASE.'lib/images/blank.gif',
236
                    'width'  => 15,
237
                    'height' => 11,
238
                    'alt'    => '',
239
                ]);
240
                $form->addHTML($display_name);
241
            }
242
243
            if ($media_id) $form->addTagOpen('div');
244
245
            if ($info['sum']) {
246
                $form->addTagOpen('span')->addClass('sum');
247
                if (!$media_id) $form->addHTML(' – ');
248
                $form->addHTML('<bdi>'. hsc($info['sum']) .'</bdi>');
249
                $form->addTagClose('span');
250
            }
251
252
            $form->addTagOpen('span')->addClass('user');
253
            if ($info['user']) {
254
                $form->addHTML('<bdi>'. editorinfo($info['user']) .'</bdi>');
255
                if (auth_ismanager()) {
256
                    $form->addHTML(' <bdo dir="ltr">('. $info['ip'] .')</bdo>');
257
                }
258
            } else {
259
                $form->addHTML('<bdo dir="ltr">' .$info['ip'] .'</bdo>');
260
            }
261
            $form->addTagClose('span');
262
263
            html_sizechange($info['sizechange'], $form);
0 ignored issues
show
Documentation introduced by
$form is of type object<dokuwiki\Form\Form>, but the function expects a object<Form>|object<Doku_Form>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
264
265
            if ($media_id) $form->addTagClose('div');
266
267
            $form->addTagClose('div');
268
            $form->addTagClose('li');
269
        }
270
271
        // end of revision list
272
        $form->addTagClose('ul');
273
274
        // show button for diff view
275
        if (!$media_id) {
276
            $form->addButton('do[diff]', $lang['diff2'])->attr('type', 'submit');
277
        } else {
278
            $form->setHiddenField('mediado', 'diff');
279
            $form->addButton('', $lang['diff2'])->attr('type', 'submit');
280
        }
281
282
        $form->addTagClose('div'); // close div class=no
283
284
        // emit HTML_REVISIONSFORM_OUTPUT event, print the form
285
        Event::createAndTrigger('HTML_REVISIONSFORM_OUTPUT', $form, 'html_form_output', false);
286
287
        print DOKU_LF;
288
289
        // provide navigation for pagenated revision list (of pages and/or media files)
290
        print '<div class="pagenav">';
291
        $last = $first + $conf['recent'];
292
        if ($first > 0) {
293
            $first = $first - $conf['recent'];
294
            if ($first < 0) $first = 0;
295
            print '<div class="pagenav-prev">';
296
            if ($media_id) {
297
                print html_btn('newer',$media_id,"p",media_managerURL(array('first' => $first), '&amp;', false, true));
298
            } else {
299
                print html_btn('newer',$id,"p",array('do' => 'revisions', 'first' => $first));
300
            }
301
            print '</div>';
302
        }
303
        if ($hasNext) {
304
            print '<div class="pagenav-next">';
305
            if ($media_id) {
306
                print html_btn('older',$media_id,"n",media_managerURL(array('first' => $last), '&amp;', false, true));
307
            } else {
308
                print html_btn('older',$id,"n",array('do' => 'revisions', 'first' => $last));
309
            }
310
            print '</div>';
311
        }
312
        print '</div>';
313
314
        print DOKU_LF;
315
    }
316
317
}
318