x Sorry, these patches are not available anymore due to data migration. Please run a fresh inspection.

Menu::getName()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Larabros\Laranav\Menus;
4
5
use Illuminate\Contracts\Routing\UrlGenerator;
6
use Illuminate\Contracts\View\Factory;
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Collection;
9
10
class Menu
11
{
12
    /**
13
     * The unique name used to identify a `Menu` instance.
14
     *
15
     * @var string
16
     */
17
    protected $name;
18
19
    /**
20
     * The menu's items.
21
     *
22
     * @var Collection
23
     */
24
    protected $items;
25
26
    /**
27
     * Any configuration options for the menu.
28
     *
29
     * @var array
30
     */
31
    protected $config;
32
33
    /**
34
     * The incoming `Request` object.
35
     *
36
     * @var Request
37
     */
38
    protected $request;
39
40
    /**
41
     * An instance of `UrlGenerator` used to generate any URLs for the menu items.
42
     *
43
     * @var UrlGenerator
44
     */
45
    protected $generator;
46
47
    /**
48
     * The `Factory` instance used to generate the views.
49
     *
50
     * @var Factory
51
     */
52
    protected $viewFactory;
53
54
    /**
55
     * Create a new `Menu` instance.
56
     *
57
     * @param string       $name
58
     * @param array        $items
59
     * @param array        $config
60
     * @param UrlGenerator $generator
61
     * @param Factory      $viewFactory
62
     */
63 24
    public function __construct(
64
        $name,
65
        array $items,
66
        array $config,
67
        UrlGenerator $generator,
68
        Factory $viewFactory
69
    ) {
70 24
        $this->name        = $name;
71 24
        $this->config      = $config;
72 24
        $this->request     = $generator->getRequest();
0 ignored issues
show
Bug introduced by
The method getRequest() does not seem to exist on object<Illuminate\Contracts\Routing\UrlGenerator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
73 24
        $this->generator   = $generator;
74 24
        $this->viewFactory = $viewFactory;
75
76
        // Has to be done after other dependencies are set
77 24
        $this->items       = new Collection($this->createItems($items));
78 24
    }
79
80
    /**
81
     * Return name of `Menu` instance.
82
     *
83
     * @return string
84
     */
85 4
    public function getName()
86
    {
87 4
        return $this->name;
88
    }
89
90
    /**
91
     * Returns `Collection` of `Item` objects.
92
     *
93
     * @return Collection
94
     */
95 12
    public function getItems()
96
    {
97 12
        return $this->items;
98
    }
99
100
    /**
101
     * Adds multiple items to the menu.
102
     *
103
     * @param array $items
104
     */
105 16
    public function addItems(array $items)
106
    {
107 16
        $this->items = $this->items->merge($this->createItems($items));
108 16
    }
109
110
    /**
111
     * Adds an item to the menu.
112
     *
113
     * @param string       $title
114
     * @param array|string $item
115
     */
116 4
    public function addItem($title, $item)
117
    {
118 4
        $this->items->push($this->createItem($title, $item));
119 4
    }
120
121
    /**
122
     * Renders the menu as a HTML string and returns it.
123
     *
124
     * @return string
125
     */
126 8
    public function toHtml()
127
    {
128 8
        return $this->viewFactory
129 8
            ->make($this->config['view'], ['menuItems' => $this->items->all()])
130 8
            ->render();
131
    }
132
133
    /**
134
     * Creates and returns a `Collection` of `Items`.
135
     *
136
     * @param  array $items
137
     *
138
     * @return Collection
139
     */
140 16
    protected function createItems(array $items)
141
    {
142 16
        $itemCollection = [];
143 16
        foreach ($items as $title => $item) {
144 16
            $itemCollection[] = $this->createItem($title, $item);
145 16
        }
146 16
        return new Collection($itemCollection);
147
    }
148
149
    /**
150
     * Creates and returns a new instance of `Item`.
151
     *
152
     * @param  string        $title
153
     * @param  array|string  $item
154
     *
155
     * @return Item
156
     */
157 12
    protected function createItem($title, $item)
158
    {
159
        // The best way to be ;)
160 12
        $children = null;
161 12
        $url      = $item;
162
163
        // If `$item` is an array, then attempt to generate a URL from the
164
        // provided parameters.
165 12
        if ($this->isItemArray($item) && !$this->hasNestedItems($item)) {
166 6
            $url = $this->generateItemUrl($item);
167 6
        }
168
169
        // If `$item` is an array and has a `default` key, then it has children.
170 12
        if ($this->hasNestedItems($item)) {
171
            // Get `default` item URL
172 4
            $url = $this->generateItemUrl($item['default']);
173
174
            // Create a `Collection` of the children items
175 4
            $children = $this->createItems(array_except($item, 'default'));
0 ignored issues
show
Bug introduced by
It seems like $item defined by parameter $item on line 157 can also be of type string; however, array_except() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
176 4
        }
177
178 12
        return new Item(
179 12
            $title,
180 12
            $url,
0 ignored issues
show
Bug introduced by
It seems like $url defined by $item on line 161 can also be of type array; however, Larabros\Laranav\Menus\Item::__construct() does only seem to accept 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...
181 12
            $this->isUrlActive($url),
0 ignored issues
show
Bug introduced by
It seems like $url defined by $item on line 161 can also be of type array; however, Larabros\Laranav\Menus\Menu::isUrlActive() does only seem to accept 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...
182 12
            $children,
183 12
            $this->config['active_class'],
184 12
            $this->config['children_class']
185 12
        );
186
    }
187
188
    /**
189
     * Checks whether an item is an array and contains one of the following keys:
190
     *
191
     * - `to`
192
     * - `secure`
193
     * - `asset`
194
     * - `route`
195
     * - `action`
196
     *
197
     * @param  array|string  $item
198
     *
199
     * @return boolean
200
     */
201 20
    protected function isItemArray($item)
202
    {
203 20
        return is_array($item)
204 20
            && in_array(key($item), ['to', 'secure', 'asset', 'route', 'action']);
205
    }
206
207
    /**
208
     * Checks whether an item has a `default` key.
209
     *
210
     * @param  array|string  $item
211
     *
212
     * @return boolean
213
     */
214 20
    protected function hasNestedItems($item)
215
    {
216 20
        return is_array($item) && in_array('default', array_keys($item));
217
    }
218
219
    /**
220
     * Checks if a provided URL is active or not.
221
     *
222
     * @param  string  $url
223
     *
224
     * @return boolean
225
     */
226 20
    protected function isUrlActive($url)
227
    {
228 20
        $path = trim(str_replace($this->request->root(), '', $url), '/');
229 20
        return $this->request->is($path);
230
    }
231
232
    /**
233
     * Generates a URL using `UrlGenerator`. If `$item` is a string, then it is
234
     * returned unchanged. If `$item` is an array, the key of the array
235
     * corresponds to a method on the `UrlGenerator` instance, and the value is
236
     * passed as a parameter.
237
     *
238
     * @param  array|string $item
239
     *
240
     * @return string
241
     */
242 14
    protected function generateItemUrl($item)
243
    {
244 14
        if ($this->isItemArray($item)) {
245 10
            $type = key($item);
246 10
            return $this->generator->$type($item[$type]);
247
        }
248 4
        return $item;
249
    }
250
}
251