GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CategoryHelper   C
last analyzed

Complexity

Total Complexity 53

Size/Duplication

Total Lines 279
Duplicated Lines 6.81 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 19
loc 279
rs 6.96
c 0
b 0
f 0
wmc 53
lcom 1
cbo 4

4 Methods

Rating   Name   Duplication   Size   Complexity  
F renderNavigation() 8 98 22
F renderCategoryDropDown() 11 96 19
A renderMainCategories() 0 15 3
B renderOptions() 0 40 9

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like CategoryHelper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CategoryHelper, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace phpMyFAQ\Helper;
4
5
/**
6
 * Helper class for phpMyFAQ categories.
7
 *
8
 *
9
 *
10
 * This Source Code Form is subject to the terms of the Mozilla Public License,
11
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
12
 * obtain one at http://mozilla.org/MPL/2.0/.
13
 *
14
 * @package phpMyFAQ
15
 * @author Thorsten Rinne <[email protected]>
16
 * @copyright 2009-2019 phpMyFAQ Team
17
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
18
 * @link https://www.phpmyfaq.de
19
 * @since 2009-09-07
20
 */
21
22
use phpMyFAQ\Helper;
23
use phpMyFAQ\Link;
24
25
if (!defined('IS_VALID_PHPMYFAQ')) {
26
    exit();
27
}
28
29
/**
30
 * PMF_CategoryHelper.
31
 *
32
 * @package phpMyFAQ
33
 * @author Thorsten Rinne <[email protected]>
34
 * @copyright 2009-2019 phpMyFAQ Team
35
 * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
36
 * @link https://www.phpmyfaq.de
37
 * @since 2009-09-07
38
 */
39
class CategoryHelper extends Helper
40
{
41
    /**
42
     * Renders the main navigation.
43
     *
44
     * @param int $activeCategory Selected category
45
     *
46
     * @return string
47
     */
48
    public function renderNavigation($activeCategory = 0)
49
    {
50
        global $sids, $PMF_LANG;
51
52
        $open = 0;
53
        $output = '';
54
        $numCategories = $this->Category->height();
55
        $numFaqs = $this->Category->getNumberOfRecordsOfCategory();
56
57
        if ($numCategories > 0) {
58
            for ($y = 0; $y < $numCategories; $y = $this->Category->getNextLineTree($y)) {
59
                list($hasChild, $name, $categoryId, $description, $active) = $this->Category->getLineDisplay($y);
60
61
                if (!$active) {
62
                    continue;
63
                }
64
65
                if ($activeCategory == $categoryId) {
66
                    $isActive = true;
67
                } else {
68
                    $isActive = false;
69
                }
70
71
                $level = $this->Category->treeTab[$y]['level'];
72
                $leveldiff = $open - $level;
73
74
                if ($this->_config->get('records.hideEmptyCategories') && !isset($numFaqs[$categoryId]) &&
75
                    '-' === $hasChild) {
76
                    continue;
77
                }
78
79 View Code Duplication
                if ($leveldiff > 1) {
80
                    $output .= '</li>';
81
                    for ($i = $leveldiff; $i > 1; --$i) {
82
                        $output .= sprintf("\n%s</ul>\n%s</li>\n",
83
                            str_repeat("\t", $level + $i + 1),
84
                            str_repeat("\t", $level + $i));
85
                    }
86
                }
87
88
                if ($level < $open) {
89
                    if (($level - $open) == -1) {
90
                        $output .= '</li>';
91
                    }
92
                    $output .= "\n".str_repeat("\t", $level + 2)."</ul>\n".str_repeat("\t", $level + 1)."</li>\n";
93
                } elseif ($level == $open && $y != 0) {
94
                    $output .= "</li>\n";
95
                }
96
97
                if ($level > $open) {
98
                    $output .= sprintf(
99
                        "\n%s<ul class=\"nav nav-list\">\n%s<li%s>",
100
                        str_repeat("\t", $level + 1),
101
                        str_repeat("\t", $level + 1),
102
                        $isActive ? ' class="active"' : ''
103
                    );
104
                } else {
105
                    $output .= sprintf(
106
                        '%s<li%s>',
107
                        str_repeat("\t", $level + 1),
108
                        $isActive ? ' class="active"' : ''
109
                    );
110
                }
111
112
                if (isset($this->Category->treeTab[$y]['symbol']) && $this->Category->treeTab[$y]['symbol'] == 'plus') {
113
                    $output .= $this->Category->addCategoryLink(
114
                        $sids, $categoryId, $name, $description, true, $isActive
115
                    );
116
                } else {
117
                    if ($this->Category->treeTab[$y]['symbol'] == 'minus') {
118
                        $name = ($this->Category->treeTab[$y]['parent_id'] === 0)
119
                                ?
120
                                $name
121
                                :
122
                                $this->Category->categoryName[$this->Category->treeTab[$y]['id']]['name'];
123
                        $output .= $this->Category->addCategoryLink(
124
                            $sids, $categoryId, $name, $description, false, $isActive
125
                        );
126
                    } else {
127
                        $output .= $this->Category->addCategoryLink(
128
                            $sids, $categoryId, $name, $description, false, $isActive
129
                        );
130
                    }
131
                }
132
                $open = $level;
133
            }
134
            if ($open > 0) {
135
                $output .= str_repeat("</li>\n\t</ul>\n\t", $open);
136
            }
137
            $output .= '</li>';
138
139
            return $output;
140
        } else {
141
            $output = '<li><a href="#">'.$PMF_LANG['no_cats'].'</a></li>';
142
        }
143
144
        return $output;
145
    }
146
147
    /**
148
     * Renders the main navigation dropdown.
149
     *
150
     * @return string
151
     */
152
    public function renderCategoryDropDown()
153
    {
154
        global $sids, $PMF_LANG;
155
156
        $open = 0;
157
        $output = '';
158
        $numCategories = $this->Category->height();
159
160
        $this->Category->expandAll();
161
162
        if ($numCategories > 0) {
163
            for ($y = 0; $y < $this->Category->height(); $y = $this->Category->getNextLineTree($y)) {
164
                list($hasChild, $categoryName, $parent, $description, $active) = $this->Category->getLineDisplay($y);
165
166
                if (!$active) {
167
                    continue;
168
                }
169
170
                $level = $this->Category->treeTab[$y]['level'];
171
                $leveldiff = $open - $level;
172
                $numChilds = $this->Category->treeTab[$y]['numChilds'];
173
174
                if (!isset($number[$parent])) {
175
                    $number[$parent] = 0;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$number was never initialized. Although not strictly required by PHP, it is generally a good practice to add $number = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
176
                }
177
178 View Code Duplication
                if ($this->_config->get('records.hideEmptyCategories') && 0 === $number[$parent] && '-' === $hasChild) {
0 ignored issues
show
Bug introduced by
The variable $number 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...
179
                    continue;
180
                }
181
182 View Code Duplication
                if ($leveldiff > 1) {
183
                    $output .= '</li>';
184
                    for ($i = $leveldiff; $i > 1; --$i) {
185
                        $output .= sprintf("\n%s</ul>\n%s</li>\n",
186
                            str_repeat("\t", $level + $i + 1),
187
                            str_repeat("\t", $level + $i));
188
                    }
189
                }
190
191
                if ($level < $open) {
192
                    if (($level - $open) == -1) {
193
                        $output .= '</li>';
194
                    }
195
                    $output .= sprintf("\n%s</ul>\n%s</li>\n",
196
                        str_repeat("\t", $level + 2),
197
                        str_repeat("\t", $level + 1));
198
                } elseif ($level == $open && $y != 0) {
199
                    $output .= "</li>\n";
200
                }
201
202
                if ($level > $open) {
203
                    $output .= sprintf(
204
                        "\n%s<ul class=\"dropdown-menu\">\n%s",
205
                        str_repeat("\t", $level + 1),
206
                        str_repeat("\t", $level + 1)
207
                    );
208
                    if ($numChilds > 0) {
209
                        $output .= '<li class="dropdown-submenu">';
210
                    } else {
211
                        $output .= '<li>';
212
                    }
213
                } else {
214
                    $output .= str_repeat("\t", $level + 1);
215
                    if ($numChilds > 0) {
216
                        $output .= '<li class="dropdown-submenu">';
217
                    } else {
218
                        $output .= '<li>';
219
                    }
220
                }
221
222
                $url = sprintf(
223
                    '%s?%saction=show&amp;cat=%d',
224
                    Link::getSystemRelativeUri(),
225
                    $sids,
226
                    $parent
227
                );
228
                $oLink = new Link($url, $this->_config);
229
                $oLink->itemTitle = $categoryName;
230
                $oLink->text = $categoryName;
231
                $oLink->tooltip = $description;
232
233
                $output .= $oLink->toHtmlAnchor();
234
                $open = $level;
235
            }
236
237
            if (isset($level) && $level > 0) {
238
                $output .= str_repeat("</li>\n\t</ul>\n\t", $level);
239
            }
240
241
            return $output;
242
        } else {
243
            $output = '<li><a href="#">'.$PMF_LANG['no_cats'].'</a></li>';
244
        }
245
246
        return $output;
247
    }
248
249
    /**
250
     * Returns all top-level categories in <li> tags.
251
     *
252
     * @return string
253
     */
254
    public function renderMainCategories()
255
    {
256
        $categories = '';
257
        foreach ($this->Category->categories as $cat) {
258
            if (0 === (int)$cat['parent_id']) {
259
                $categories .= sprintf(
260
                    '<li><a href="?action=show&cat=%d">%s</a></li>',
261
                    $cat['id'],
262
                    $cat['name']
263
                    );
264
            }
265
        }
266
267
        return $categories;
268
    }
269
270
    /**
271
     * Get all categories in <option> tags.
272
     *
273
     * @param array|int $categoryId CategoryHelper ID or array of category IDs
274
     *
275
     * @return string
276
     */
277
    public function renderOptions($categoryId)
278
    {
279
        $categories = '';
280
281
        if (!is_array($categoryId)) {
282
            $categoryId = array(
283
                array(
284
                    'category_id' => $categoryId,
285
                    'category_lang' => '',
286
                ),
287
            );
288
        } elseif (isset($categoryId['category_id'])) {
289
            $categoryId = array($categoryId);
290
        }
291
292
        $i = 0;
293
        foreach ($this->Category->getCategoryTree() as $cat) {
294
            $indent = '';
295
            for ($j = 0; $j < $cat['indent']; ++$j) {
296
                $indent .= '....';
297
            }
298
            $categories .= "\t<option value=\"".$cat['id'].'"';
299
300
            if (0 === $i && count($categoryId) === 0) {
301
                $categories .= ' selected';
302
            } else {
303
                foreach ($categoryId as $categoryid) {
304
                    if ($cat['id'] == $categoryid['category_id']) {
305
                        $categories .= ' selected';
306
                    }
307
                }
308
            }
309
310
            $categories .= '>';
311
            $categories .= $indent.$cat['name']."</option>\n";
312
            ++$i;
313
        }
314
315
        return $categories;
316
    }
317
}
318