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 ( 0b6a33...53177f )
by Sebastian
01:56
created

Menu::registerFilter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Spatie\Menu;
4
5
use Spatie\HtmlElement\HtmlElement;
6
use Spatie\Menu\Items\Link;
7
use Spatie\Menu\Traits\HtmlAttributes;
8
use Spatie\Menu\Traits\ParentAttributes;
9
10
class Menu implements Item
11
{
12
    use HtmlAttributes, ParentAttributes;
13
14
    /** @var array */
15
    protected $items = [];
16
17
    /** @var string */
18
    protected $prepend = '';
19
20
    /** @var string */
21
    protected $append = '';
22
23
    /** @var array */
24
    protected $filters = [];
25
26
    /**
27
     * @param \Spatie\Menu\Item[] ...$items
28
     */
29
    protected function __construct(Item ...$items)
30
    {
31
        $this->items = $items;
32
33
        $this->bootHtmlAttributes();
34
        $this->bootParentAttributes();
35
    }
36
37
    /**
38
     * Create a new menu, optionally prefilled with items.
39
     *
40
     * @param array $items
41
     *
42
     * @return static
43
     */
44
    public static function new(array $items = [])
45
    {
46
        return new static(...array_values($items));
47
    }
48
49
    /**
50
     * Add an item to the menu. This also applies all registered filters on the item. If a filter
51
     * returns false, the item won't be added.
52
     *
53
     * @param \Spatie\Menu\Item $item
54
     *
55
     * @return $this
56
     */
57
    public function add(Item $item)
58
    {
59
        foreach ($this->filters as $filter) {
60
            $this->applyFilter($filter, $item);
61
        }
62
63
        $this->items[] = $item;
64
65
        return $this;
66
    }
67
68
    /**
69
     * Apply a filter to an item. Returns the result of the filter.
70
     *
71
     * @param callable $filter
72
     * @param \Spatie\Menu\Item $item
73
     */
74
    protected function applyFilter(callable $filter, Item $item)
75
    {
76
        $type = first_parameter_type($filter);
77
78
        if (!item_matches_type($item, $type)) {
79
            return;
80
        }
81
82
        $filter($item);
83
    }
84
85
    /**
86
     * Iterate over all the items and apply a callback. If you typehint the
87
     * item parameter in the callable, it wil only be applied to items of that type.
88
     *
89
     * @param callable $callable
90
     *
91
     * @return $this
92
     */
93
    public function each(callable $callable)
94
    {
95
        $type = first_parameter_type($callable);
96
97
        foreach ($this->items as $item) {
98
            if (!item_matches_type($item, $type)) {
99
                continue;
100
            }
101
102
            $callable($item);
103
        }
104
105
        return $this;
106
    }
107
108
    /**
109
     * Register a filter to the menu. When an item is added, all filters will be applied to the
110
     * item. If you typehint the item
111
     * parameter in the callable, it wil only be applied to items of that type.
112
     *
113
     * @param callable $callable
114
     *
115
     * @return $this
116
     */
117
    public function registerFilter(callable $callable)
118
    {
119
        $this->filters[] = $callable;
120
121
        return $this;
122
    }
123
124
    /**
125
     * Apply a callable to all existing items, and register it as a filter so it will get applied
126
     * to all new items too. If you typehint the item parameter in the callable, it wil only be
127
     * applied to items of that type.
128
     *
129
     * @param callable $callable
130
     *
131
     * @return $this
132
     */
133
    public function applyToAll(callable $callable)
134
    {
135
        $this->each($callable);
136
        $this->registerFilter($callable);
137
138
        return $this;
139
    }
140
141
    /**
142
     * Prepend a string of html to the menu on render.
143
     *
144
     * @param string $prefix
145
     *
146
     * @return $this
147
     */
148
    public function prefixLinks(string $prefix)
149
    {
150
        return $this->applyToAll(function (Link $link) use ($prefix) {
151
            $link->prefix($prefix);
152
        });
153
    }
154
155
    /**
156
     * Prepend the menu with a string of html on render.
157
     *
158
     * @param string $prepend
159
     *
160
     * @return $this
161
     */
162
    public function prepend(string $prepend)
163
    {
164
        $this->prepend = $prepend;
165
166
        return $this;
167
    }
168
169
    /**
170
     * Prepend the menu with a string of html on render if a certain condition is met.
171
     *
172
     * @param bool $condition
173
     * @param string $prepend
174
     *
175
     * @return $this
176
     */
177
    public function prependIf(bool $condition, string $prepend)
178
    {
179
        if ($condition) {
180
            return $this->prepend($prepend);
181
        }
182
183
        return $this;
184
    }
185
186
    /**
187
     * Append a string of html to the menu on render.
188
     *
189
     * @param string $append
190
     *
191
     * @return $this
192
     */
193
    public function append(string $append)
194
    {
195
        $this->append = $append;
196
197
        return $this;
198
    }
199
200
    /**
201
     * Append the menu with a string of html on render if a certain condition is met.
202
     *
203
     * @param bool $condition
204
     * @param string $append
205
     *
206
     * @return static
207
     */
208
    public function appendIf(bool $condition, string $append)
209
    {
210
        if ($condition) {
211
            return $this->append($append);
212
        }
213
214
        return $this;
215
    }
216
217
    /**
218
     * Determine whether the menu is active.
219
     *
220
     * @return bool
221
     */
222
    public function isActive() : bool
223
    {
224
        foreach ($this->items as $item) {
225
            if ($item->isActive()) {
226
                return true;
227
            }
228
        }
229
230
        return false;
231
    }
232
233
    /**
234
     * Set multiple items in the menu as active based on a callable that filters through items.
235
     * If you typehint the item parameter in the callable, it wil only be applied to items of
236
     * that type.
237
     *
238
     * @param callable|string $patternOrCallable
239
     * @param string $root
240
     *
241
     * @return $this
242
     */
243
    public function setActive($patternOrCallable, string $root = '/')
244
    {
245
        if (is_string($patternOrCallable)) {
246
            return $this->setActiveFromUrl($patternOrCallable, $root);
247
        }
248
249
        if (is_callable($patternOrCallable)) {
250
            return $this->setActiveFromCallable($patternOrCallable);
251
        }
252
253
        throw new \InvalidArgumentException('`setActive` requires a pattern or a callable');
254
    }
255
256
    /**
257
     * @param string $url
258
     * @param string $root
259
     *
260
     * @return $this
261
     */
262
    public function setActiveFromUrl(string $url, string $root = '/')
263
    {
264
        $requestUrl = url_parts($url);
265
        $requestRoot = strip_trailing_slashes($root, '/');
266
267
        $this->applyToAll(function (Link $link) use ($requestUrl, $requestRoot) {
268
269
            $url = url_parts($link->getUrl());
270
271
            // If the menu item is on a different host it can't be active.
272
            if ($url['host'] !== '' && $url['host'] !== $requestUrl['host']) {
273
                return;
274
            }
275
276
            // If the request url or the link url is on the root, only set exact matches active.
277
            if (
278
                $requestUrl['path'] === $requestRoot ||
279
                $url['path'] === $requestRoot
280
            ) {
281
                if ($url['path'] === $requestUrl['path']) {
282
                    $link->setActive();
283
                }
284
285
                return;
286
            }
287
288
            // The menu item is active if it's path starts with the request path.
289
            if (strpos($url['path'], $requestUrl['path']) === 0) {
290
                $link->setActive();
291
            };
292
        });
293
294
        return $this;
295
    }
296
297
    /**
298
     * @param callable $callable
299
     *
300
     * @return $this
301
     */
302
    public function setActiveFromCallable(callable $callable)
303
    {
304
        $type = first_parameter_type($callable);
305
306
        return $this->applyToAll(function (Item $item) use ($callable, $type) {
307
            if (!item_matches_type($item, $type)) {
308
                return;
309
            }
310
311
            if ($callable($item)) {
312
                $item->setActive();
313
            }
314
        });
315
    }
316
317
    /**
318
     * @return string
319
     */
320
    public function render() : string
321
    {
322
        $contents = HtmlElement::render(
323
            'ul',
324
            $this->htmlAttributes->toArray(),
325
            array_map(function (Item $item) {
326
                return HtmlElement::render(
327
                    $item->isActive() ? 'li.active' : 'li',
328
                    $item->getParentAttributes(),
329
                    $item->render()
330
                );
331
            }, $this->items)
332
        );
333
334
        return "{$this->prepend}{$contents}{$this->append}";
335
    }
336
337
    /**
338
     * @return string
339
     */
340
    public function __toString() : string
341
    {
342
        return $this->render();
343
    }
344
}
345