Completed
Push — master ( c72293...85ffb1 )
by Florian
05:33 queued 02:31
created

Builder::findItem()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7.0145

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 14
cts 15
cp 0.9333
rs 8.6026
c 0
b 0
f 0
cc 7
nc 6
nop 3
crap 7.0145
1
<?php
2
3
namespace JeroenNoten\LaravelAdminLte\Menu;
4
5
use Illuminate\Support\Arr;
6
7
class Builder
8
{
9
    public $menu = [];
10
11
    /**
12
     * @var array
13
     */
14
    private $filters;
15
16 41
    public function __construct(array $filters = [])
17
    {
18 41
        $this->filters = $filters;
19 41
    }
20
21 41
    public function add(...$newItems)
22
    {
23 41
        $items = $this->transformItems($newItems);
24
25 41
        foreach ($items as $item) {
26 41
            array_push($this->menu, $item);
27
        }
28 41
    }
29
30 4
    public function addAfter($itemKey, ...$newItems)
31
    {
32 4
        $this->addItem($itemKey, 'after', ...$newItems);
33 4
    }
34
35 4
    public function addBefore($itemKey, ...$newItems)
36
    {
37 4
        $this->addItem($itemKey, 'before', ...$newItems);
38 4
    }
39
40 3
    public function addIn($itemKey, ...$newItems)
41
    {
42 3
        $this->addItem($itemKey, 'in', ...$newItems);
43 3
    }
44
45 4
    public function remove($itemKey)
46
    {
47 4
        $completeArrayPath = $previousArrayPath = '';
48 4
        $itemPath = $this->findItem($itemKey, $this->menu);
49 4
        if (is_array($itemPath)) {
50 2
            foreach ($itemPath as $key => $value) {
51 2
                if ($completeArrayPath === '') {
52 2
                    $completeArrayPath .= "$value";
53
                } else {
54 2
                    $completeArrayPath .= ".submenu.$value";
55
                }
56
            }
57 2
            $itemPath = $completeArrayPath;
58 2
            $previousArrayPath = preg_replace('/.[^.]*$/', '', $itemPath);
59
        }
60 4
        Arr::forget($this->menu, $itemPath);
61
62 4
        $this->menu = array_values($this->menu);
63
64 4
        if ($previousArrayPath !== '') {
65 2
            $oldArray = Arr::get($this->menu, $previousArrayPath);
66 2
            $oldArray = array_values($oldArray);
67 2
            Arr::set($this->menu, $previousArrayPath, $oldArray);
68
        }
69 4
    }
70
71 3
    public function itemKeyExists($itemKey)
72
    {
73 3
        $position = $this->findItem($itemKey, $this->menu);
74
75 3
        if ((! is_array($position) && $position !== null) || (is_array($position) && end($position) !== null)) {
76 3
            return true;
77
        }
78
79 2
        return false;
80
    }
81
82 41
    public function transformItems($items)
83
    {
84 41
        return array_filter(array_map([$this, 'applyFilters'], $items));
85
    }
86
87 11
    protected function addItem($itemKey, $direction, ...$newItems)
88
    {
89 11
        $items = $this->transformItems($newItems);
90 11
        $position = $this->findItem($itemKey, $this->menu);
91
92 11
        if ($position !== null) {
93 11
            $completeArrayPath = $lastKey = '';
0 ignored issues
show
Unused Code introduced by
$lastKey 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...
Unused Code introduced by
$completeArrayPath 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...
94
95 11
            if (is_array($position)) {
96 2
                $completeArrayPath = implode('.submenu.', $position);
97 2
                $lastKey = end($position);
98
            } else {
99 9
                $completeArrayPath = $lastKey = $position;
100
            }
101
102 11
            if ($direction == 'in' || ! is_array($position)) {
103 9
                $arrayPath = $completeArrayPath;
104 2
            } elseif (is_array($position)) {
105 2
                $arrayPath = substr($completeArrayPath, 0, -(strlen(".$lastKey")));
106
            }
107
108 11
            if ($position == $lastKey && $direction != 'in') {
109 6
                array_splice($this->menu, $position + ($direction == 'after' ? 1 : 0), 0, $items);
110
            } else {
111 5
                $menuItems = Arr::get($this->menu, $arrayPath);
0 ignored issues
show
Bug introduced by
The variable $arrayPath 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...
112
113 5
                if ($direction == 'in') {
114 3
                    if (! isset($menuItems['submenu'])) {
115 3
                        $menuItems['submenu'] = [];
116 3
                        $menuItems = $this->transformItems([$menuItems]);
117 3
                        $menuItems = $menuItems[0];
118 3
                        $menuItems['submenu'] = [];
119
                    }
120
121 3
                    $menuItems['submenu'] = array_merge($menuItems['submenu'], $items);
122
                } else {
123 2
                    array_splice($menuItems, $lastKey + ($direction == 'after' ? 1 : 0), 0, $items);
124
                }
125
126 5
                Arr::set($this->menu, $arrayPath, $this->applyFilters($menuItems));
127
            }
128
        }
129 11
    }
130
131 18
    protected function findItem($itemKey, $items, $childPositionOld = null)
0 ignored issues
show
Unused Code introduced by
The parameter $childPositionOld is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
132
    {
133 18
        $childPositions = [];
134 18
        foreach ($items as $key => $item) {
135 18
            if (isset($item['key']) && $item['key'] == $itemKey) {
136 18
                return $key;
137 7
            } elseif (isset($item['submenu'])) {
138 6
                $newKey = $this->findItem($itemKey, $item['submenu']);
139
140 6
                if ($newKey === null) {
141 2
                    continue;
142
                }
143
144 6
                $childPositions[] = $key;
145 6
                if (! is_array($newKey)) {
146 6
                    $childPositions[] = $newKey;
147
                } else {
148
                    $childPositions = array_merge($childPositions, $newKey);
149
                }
150
151 6
                return $childPositions;
152
            }
153
        }
154 2
    }
155
156 41
    protected function applyFilters($item)
157
    {
158 41
        if (is_string($item)) {
159 1
            return $item;
160
        }
161
162 40
        foreach ($this->filters as $filter) {
163 39
            $item = $filter->transform($item, $this);
164
        }
165
166 40
        return $item;
167
    }
168
}
169