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.
Completed
Push — master ( 1e8ae2...b461dc )
by Sebastian
02:42
created

Menu::prependIf()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
3
namespace Spatie\Menu;
4
5
use ReflectionFunction;
6
use ReflectionParameter;
7
use Spatie\HtmlElement\Html;
8
use Spatie\Menu\Items\Link;
9
use Spatie\Menu\Traits\HtmlAttributes;
10
use Spatie\Menu\Traits\ParentAttributes;
11
12
class Menu implements Item
13
{
14
    use HtmlAttributes, ParentAttributes;
15
16
    /** @var array */
17
    protected $items = [];
18
19
    /** @var string */
20
    protected $prepend = '';
21
22
    /** @var string */
23
    protected $append = '';
24
25
    /** @var array */
26
    protected $filters = [];
27
28
    /**
29
     * @param \Spatie\Menu\Item[] ...$items
30
     */
31
    protected function __construct(Item ...$items)
32
    {
33
        $this->items = $items;
34
    }
35
36
    /**
37
     * Create a new menu, optionally prefilled with items.
38
     *
39
     * @param array $items
40
     *
41
     * @return static
42
     */
43
    public static function new(array $items = [])
44
    {
45
        return new static(...$items);
46
    }
47
48
    /**
49
     * Add an item to the menu. This also applies all registered filters on the item. If a filter
50
     * returns false, the item won't be added.
51
     *
52
     * @param \Spatie\Menu\Item $item
53
     *
54
     * @return $this
55
     */
56
    public function add(Item $item)
57
    {
58
        if ($this->applyFilters($item) === false) {
59
            return $this;
60
        }
61
62
        $this->items[] = $item;
63
64
        return $this;
65
    }
66
67
    /**
68
     * Applies all the currently registered filters to an item.
69
     *
70
     * @param \Spatie\Menu\Item $item
71
     *
72
     * @return bool
73
     */
74
    protected function applyFilters(Item $item) : bool
75
    {
76
        foreach ($this->filters as $filter) {
77
            if ($this->applyFilter($filter, $item) === false) {
78
                return false;
79
            }
80
        }
81
82
        return true;
83
    }
84
85
    /**
86
     * Apply a filter to an item. Returns the result of the filter.
87
     *
88
     * @param callable $filter
89
     * @param \Spatie\Menu\Item $item
90
     *
91
     * @return mixed
92
     */
93
    protected function applyFilter(callable $filter, Item $item)
94
    {
95
        $type = $this->determineFirstParameterType($filter);
96
97
        if ($type !== null && !$item instanceof $type) {
98
            return;
99
        }
100
101
        return $filter($item);
102
    }
103
104
    /**
105
     * Map through all the items and return an array containing the result. If you typehint the
106
     * item parameter in the callable, it wil only be applied to items of that type.
107
     *
108
     * @param callable $callable
109
     *
110
     * @return array
111
     */
112
    public function map(callable $callable) : array
113
    {
114
        $type = $this->determineFirstParameterType($callable);
115
116
        $items = $this->items;
117
118
        if ($type !== null) {
119
            $items = array_filter($items, function (Item $item) use ($type) {
120
                return $item instanceof $type;
121
            });
122
        }
123
124
        return array_map($callable, $items);
125
    }
126
127
    /**
128
     * Iterate over all the items and apply a callback. If you typehint the
129
     * item parameter in the callable, it wil only be applied to items of that type.
130
     *
131
     * @param callable $callable
132
     *
133
     * @return $this
134
     */
135 View Code Duplication
    public function each(callable $callable)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
136
    {
137
        $type = $this->determineFirstParameterType($callable);
138
139
        foreach ($this->items as $item) {
140
            if ($type !== null && !$item instanceof $type) {
141
                continue;
142
            }
143
144
            $callable($item);
145
        }
146
147
        return $this;
148
    }
149
150
    /**
151
     * Register a filter to the menu. When an item is added, all filters will be applied to the
152
     * item. If a filter returns false, the item won't be added. If you typehint the item
153
     * parameter in the callable, it wil only be applied to items of that type.
154
     *
155
     * @param callable $callable
156
     *
157
     * @return $this
158
     */
159
    public function registerFilter(callable $callable)
160
    {
161
        $this->filters[] = $callable;
162
163
        return $this;
164
    }
165
166
    /**
167
     * Apply a callable to all existing items, and register it as a filter so it will get applied
168
     * to all new items too. If you typehint the item parameter in the callable, it wil only be
169
     * applied to items of that type.
170
     *
171
     * @param callable $callable
172
     *
173
     * @return $this
174
     */
175
    public function applyToAll(callable $callable)
176
    {
177
        $this->each($callable);
178
        $this->registerFilter($callable);
179
180
        return $this;
181
    }
182
183
    /**
184
     * Determine the type of the first parameter of a callable.
185
     *
186
     * @param callable $callable
187
     *
188
     * @return string|null
189
     */
190
    protected function determineFirstParameterType(callable $callable)
191
    {
192
        $reflection = new ReflectionFunction($callable);
193
194
        $parameterTypes = array_map(function (ReflectionParameter $parameter) {
195
            return $parameter->getClass() ? $parameter->getClass()->name : null;
196
        }, $reflection->getParameters());
197
198
        return $parameterTypes[0] ?? null;
199
    }
200
201
    /**
202
     * Prepend a string of html to the menu on render.
203
     *
204
     * @param string $prefix
205
     *
206
     * @return $this
207
     */
208
    public function prefixLinks(string $prefix)
209
    {
210
        return $this->applyToAll(function (Link $link) use ($prefix) {
211
            $link->prefix($prefix);
212
        });
213
    }
214
215
    /**
216
     * Prepend the menu with a string of html on render.
217
     *
218
     * @param string $prepend
219
     *
220
     * @return $this
221
     */
222
    public function prepend(string $prepend)
223
    {
224
        $this->prepend = $prepend;
225
226
        return $this;
227
    }
228
229
    /**
230
     * Prepend the menu with a string of html on render if a certain condition is met.
231
     *
232
     * @param bool $condition
233
     * @param string $prepend
234
     *
235
     * @return $this
236
     */
237
    public function prependIf(bool $condition, string $prepend)
238
    {
239
        if ($condition) {
240
            $this->prepend($prepend);
241
        }
242
243
       return $this;
244
    }
245
246
    /**
247
     * Append a string of html to the menu on render.
248
     *
249
     * @param string $append
250
     *
251
     * @return $this
252
     */
253
    public function append(string $append)
254
    {
255
        $this->append = $append;
256
257
        return $this;
258
    }
259
260
    /**
261
     * Append the menu with a string of html on render if a certain condition is met.
262
     *
263
     * @param bool $condition
264
     * @param string $append
265
     *
266
     * @return $this
267
     */
268
    public function appendIf(bool $condition, string $append)
269
    {
270
        if ($condition) {
271
            $this->append($append);
272
        }
273
274
        return $this;
275
    }
276
277
    /**
278
     * Determine whether the menu is active.
279
     *
280
     * @return bool
281
     */
282
    public function isActive() : bool
283
    {
284
        foreach ($this->items as $item) {
285
            if ($item->isActive()) {
286
                return true;
287
            }
288
        }
289
290
        return false;
291
    }
292
293
    /**
294
     * Set multiple items in the menu as active based on a callable that filters through items.
295
     * If you typehint the item parameter in the callable, it wil only be applied to items of
296
     * that type.
297
     *
298
     * @param callable $callable
299
     *
300
     * @return $this
301
     */
302 View Code Duplication
    public function setActive(callable $callable)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
303
    {
304
        $type = $this->determineFirstParameterType($callable);
305
306
        foreach ($this->items as $item) {
307
            if ($type !== null && !$item instanceof $type) {
308
                continue;
309
            }
310
311
            if ($callable($item)) {
312
                $item->setActive();
313
            }
314
        }
315
316
        return $this;
317
    }
318
319
    /**
320
     * @return string
321
     */
322
    public function render() : string
323
    {
324
        $menu = Html::el(
325
            'ul',
326
            $this->attributes()->toArray(),
327
            $this->map(function (Item $item) {
328
                return Html::el(
329
                    $item->isActive() ? 'li.active' : 'li',
330
                    $item->getParentAttributes(),
331
                    $item->render()
332
                );
333
            })
334
        );
335
336
        return "{$this->prepend}{$menu}{$this->append}";
337
    }
338
339
    /**
340
     * @return string
341
     */
342
    public function __toString() : string
343
    {
344
        return $this->render();
345
    }
346
}
347