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 ( 53177f...cf3086 )
by Sebastian
02:24
created

Menu::applyToAll()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

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