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

Recent.php$0 ➔ difflink()   B

Complexity

Conditions 6

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
dl 0
loc 28
rs 8.8497
c 0
b 0
f 0
1
<?php
2
3
namespace dokuwiki\Ui;
4
5
use dokuwiki\ChangeLog\MediaChangeLog;
6
use dokuwiki\Form\Form;
7
8
/**
9
 * DokuWiki Recent Interface
10
 *
11
 * @package dokuwiki\Ui
12
 */
13
class Recent extends Ui
14
{
15
    protected $first;
16
    protected $show_changes;
17
18
    /** 
19
     * Recent Ui constructor
20
     *
21
     * @param int $first  skip the first n changelog lines
22
     * @param string $show_changes  type of changes to show; pages, mediafiles, or both
23
     */
24
    public function __construct($first = 0, $show_changes = 'both')
25
    {
26
        $this->first        = $first;
27
        $this->show_changes = $show_changes;
28
    }
29
30
    /**
31
     * Display recent changes
32
     *
33
     * @author Andreas Gohr <[email protected]>
34
     * @author Matthias Grimm <[email protected]>
35
     * @author Ben Coburn <[email protected]>
36
     * @author Kate Arzamastseva <[email protected]>
37
     * @author Satoshi Sahara <[email protected]>
38
     *
39
     * @triggers HTMLFORM_RECENT_OUTPUT
40
     * @return void
41
     */
42
    public function show()
43
    {
44
        global $lang;
45
        global $ID;
46
47
        // get recent items, and set correct pagenation parameters (first, hasNext)
48
        $first = $this->first;
49
        $hasNext = false;
50
        $recents = $this->getRecents($first, $hasNext);
51
52
        // print intro
53
        print p_locale_xhtml('recent');
54
55
        if (getNS($ID) != '') {
56
            print '<div class="level1"><p>'
57
                . sprintf($lang['recent_global'], getNS($ID), wl('', 'do=recent'))
58
                .'</p></div>';
59
        }
60
61
        // create the form
62
        $form = new Form(['id'=>'dw__recent', 'method'=>'GET', 'action'=> wl($ID), 'class'=>'changes']);
63
        $form->addTagOpen('div')->addClass('no');
64
        $form->setHiddenField('sectok', null);
65
        $form->setHiddenField('do', 'recent');
66
        $form->setHiddenField('id', $ID);
67
68
        // show dropdown selector, whether include not only recent pages but also recent media files?
69
        if ($conf['mediarevisions']) {
0 ignored issues
show
Bug introduced by
The variable $conf does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
70
            $this->addRecentItemSelector($form);
71
        }
72
73
        // start listing of recent items
74
        $form->addTagOpen('ul');
75
        foreach ($recents as $recent) {
76
            $objRevInfo = $this->getObjRevInfo($recent);
77
            $class = ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor': '';
78
            $form->addTagOpen('li')->addClass($class);
79
            $form->addTagOpen('div')->addClass('li');
80
            $html = implode(' ', [
81
                $objRevInfo->itemIcon(),          // filetype icon
82
                $objRevInfo->editDate(),          // edit date and time
83
                $objRevInfo->difflink(),          // link to diffview icon
84
                $objRevInfo->revisionlink(),      // linkto revisions icon
85
                $objRevInfo->itemName(),          // name of page or media
86
                $objRevInfo->editSummary(),       // edit summary
87
                $objRevInfo->editor(),            // editor info
88
                html_sizechange($recent['sizechange']), // size change indicator
89
            ]);
90
            $form->addHTML($html);
91
            $form->addTagClose('div');
92
            $form->addTagClose('li');
93
        }
94
        $form->addTagClose('ul');
95
96
        $form->addTagClose('div'); // close div class=no
97
98
        // provide navigation for pagenated recent list (of pages and/or media files)
99
        $form->addHTML($this->htmlNavigation($first, $hasNext));
100
101
        // print form that might be modified by HTMLFORM_RECENT_OUTPUT event handlers
102
        print $form->toHTML('recent');
103
    }
104
105
    /**
106
     * Get recent items, and set correct pagenation parameters (first, hasNext)
107
     *
108
     * @param int  $first
109
     * @param bool $hasNext
110
     * @return array  recent items to be shown in a pagenated list
111
     *
112
     * @see also dokuwiki\Changelog::getRevisionInfo()
113
     */
114
    protected function getRecents(&$first, &$hasNext)
115
    {
116
        global $ID, $conf;
117
118
        $flags = 0;
119
        if ($this->show_changes == 'mediafiles' && $conf['mediarevisions']) {
120
            $flags = RECENTS_MEDIA_CHANGES;
121
        } elseif ($this->show_changes == 'pages') {
122
            $flags = 0;
123
        } elseif ($conf['mediarevisions']) {
124
            $flags = RECENTS_MEDIA_PAGES_MIXED;
125
        }
126
127
        /* we need to get one additionally log entry to be able to
128
         * decide if this is the last page or is there another one.
129
         * This is the cheapest solution to get this information.
130
         */
131
        $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
0 ignored issues
show
Security Bug introduced by
It seems like getNS($ID) targeting getNS() can also be of type false; however, getRecents() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
132
        if (count($recents) == 0 && $first != 0) {
133
            $first = 0;
134
            $recents = getRecents($first, $conf['recent'] + 1, getNS($ID), $flags);
0 ignored issues
show
Security Bug introduced by
It seems like getNS($ID) targeting getNS() can also be of type false; however, getRecents() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
135
        }
136
137
        $hasNext = false;
138
        if (count($recents) > $conf['recent']) {
139
            $hasNext = true;
140
            array_pop($recents); // remove extra log entry
141
        }
142
        return $recents;
143
    }
144
145
    /**
146
     * Navigation buttons for Pagenation (prev/next)
147
     *
148
     * @param int  $first
149
     * @param bool $hasNext
150
     * @return array  html
151
     */
152
    protected function htmlNavigation($first, $hasNext)
153
    {
154
        global $conf, $lang;
155
156
        $last = $first + $conf['recent'];
157
        $html = '<div class="pagenav">';
158
        if ($first > 0) {
159
            $first = max($first - $conf['recent'], 0);
160
            $html.= '<div class="pagenav-prev">';
161
            $html.= '<button type="submit" name="first['.$first.']" accesskey="n"'
162
                  . ' title="'.$lang['btn_newer'].' [N]" class="button show">'
163
                  . $lang['btn_newer']
164
                  . '</button>';
165
            $html.= '</div>';
166
        }
167
        if ($hasNext) {
168
            $html.= '<div class="pagenav-next">';
169
            $html.= '<button type="submit" name="first['.$last.']" accesskey="p"'
170
                  . ' title="'.$lang['btn_older'].' [P]" class="button show">'
171
                  . $lang['btn_older']
172
                  . '</button>';
173
            $html.= '</div>';
174
        }
175
        $html.= '</div>';
176
        return $html;
177
    }
178
179
    /**
180
     * Add dropdown selector of item types to the form instance
181
     *
182
     * @param Form $form
183
     * @return void
184
     */
185
    protected function addRecentItemSelector(Form $form)
186
    {
187
        global $lang;
188
189
        $form->addTagOpen('div')->addClass('changeType');
190
        $options = array(
191
                    'pages'      => $lang['pages_changes'],
192
                    'mediafiles' => $lang['media_changes'],
193
                    'both'       => $lang['both_changes'],
194
        );
195
        $form->addDropdown('show_changes', $options, $lang['changes_type'])
196
                ->val($this->show_changes)->addClass('quickselect');
197
        $form->addButton('do[recent]', $lang['btn_apply'])->attr('type','submit');
198
        $form->addTagClose('div');
199
    }
200
201
    /**
202
     * Returns instance of objRevInfo
203
     * @param array $info  Revision info structure of page or media
204
     * @return objRevInfo object (anonymous class)
205
     */
206
    protected function getObjRevInfo(array $info)
207
    {
208
        return new class ($info) // anonymous class (objRevInfo)
209
        {
210
            protected $info;
211
212
            public function __construct(array $info)
213
            {
214
                $this->info = $info;
215
            }
216
217
            // fileicon of the page or media file
218
            public function itemIcon()
219
            {
220
                $id = $this->info['id'];
221
                if (isset($this->info['media'])) {
222
                    $html = media_printicon($id);
223
                } else {
224
                    $html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
225
                }
226
                return $html;
227
            }
228
229
            // edit date and time of the page or media file
230
            public function editDate()
231
            {
232
                $date = $this->info['date'];
233
                $html = '<span class="date">'. dformat($date) .'</span>';
234
                return $html;
235
            }
236
237
            // icon difflink
238
            public function difflink()
239
            {
240
                global $lang;
241
                $id = $this->info['id'];
242
                $diff = false;
243
244
                if (isset($this->info['media'])) {
245
                    $revs = (new MediaChangeLog($id))->getRevisions(0, 1);
246
                    $diff = (count($revs) && file_exists(mediaFN($id)));
247
                    if ($diff) {
248
                        $href = media_managerURL(
249
                            ['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&'
250
                        );
251
                    }
252
                } else {
253
                    $href = wl($id, "do=diff", false, '&');
254
                }
255
256
                if (isset($this->info['media']) && !$diff) {
257
                    $html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
258
                } else {
259
                    $html = '<a href="'.$href.'" class="diff_link">'
0 ignored issues
show
Bug introduced by
The variable $href 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...
260
                          . '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
261
                          . ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
262
                          . '</a>';
263
                }
264
                return $html;
265
            }
266
267
            // icon revision link
268
            public function revisionlink()
269
            {
270
                global $lang;
271
                $id = $this->info['id'];
272
                if (isset($this->info['media'])) {
273
                    $href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&');
274
                } else {
275
                    $href = wl($id, "do=revisions", false, '&');
276
                }
277
                $html = '<a href="'.$href.'" class="revisions_link">'
278
                      . '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
279
                      . ' title="'.$lang['btn_revs'].'" alt="'.$lang['btn_revs'].'" />'
280
                      . '</a>';
281
                return $html;
282
            }
283
284
            // name of the page or media file
285
            public function itemName()
286
            {
287
                $id = $this->info['id'];
288
                if (isset($this->info['media'])) {
289
                    $href = media_managerURL(['tab_details'=>'view', 'image'=> $id, 'ns'=> getNS($id)], '&');
290
                    $class = file_exists(mediaFN($id)) ? 'wikilink1' : 'wikilink2';
291
                    $html = '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>';
292
                } else {
293
                    $html = html_wikilink(':'.$id, (useHeading('navigation') ? null : $id));
294
                }
295
                return $html;
296
            }
297
298
            // edit summary
299
            public function editSummary()
300
            {
301
                $html = '<span class="sum">';
302
                $html.= ' – '. hsc($this->info['sum']);
303
                $html.= '</span>';
304
                return $html;
305
            }
306
307
            // editor of the page or media file
308
            public function editor()
309
            {
310
                $html = '<span class="user">';
311
                if ($this->info['user']) {
312
                    $html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
313
                    if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
314
                } else {
315
                    $html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
316
                }
317
                $html.= '</span>';
318
                return $html;
319
            }
320
        }; // end of anonymous class (objRevInfo)
321
    }
322
323
}
324