Completed
Push — master ( f1008b...f475f6 )
by Florian
03:33
created

ActiveChecker::isActive()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 5
cts 5
cp 1
rs 9.7998
c 0
b 0
f 0
cc 4
nc 3
nop 1
crap 4
1
<?php
2
3
namespace JeroenNoten\LaravelAdminLte\Menu;
4
5
use Illuminate\Contracts\Routing\UrlGenerator;
6
use Illuminate\Http\Request;
7
use Illuminate\Support\Str;
8
9
class ActiveChecker
10
{
11
    /**
12
     * The request instance.
13
     *
14
     * @var Request
15
     */
16
    private $request;
17
18
    /**
19
     * The url generator instance.
20
     *
21
     * @var UrlGenerator
22
     */
23
    private $url;
24
25
    /**
26
     * Map between menu item properties and their respective test method.
27
     *
28
     * @var array
29
     */
30
    private $tests;
31
32
    /**
33
     * Constructor.
34
     *
35
     * @param Request $request
36
     * @param UrlGenerator $url
37
     */
38 61
    public function __construct(Request $request, UrlGenerator $url)
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
39
    {
40 61
        $this->request = $request;
41 61
        $this->url = $url;
42
43
        // Fill the map with tests. These tests will check if a menu item is
44
        // active or not.
45
46 61
        $this->tests = [
47 61
            'submenu' => [$this, 'containsActive'],
48 61
            'active'  => [$this, 'isExplicitActive'],
49 61
            'href'    => [$this, 'checkPattern'],
50 61
            'url'     => [$this, 'checkPattern'],
51
        ];
52 61
    }
53
54
    /**
55
     * Checks if a menu item is currently active. Active items will be
56
     * highlighted.
57
     *
58
     * @param mixed $item The menu item to check
59
     * @return bool
60
     */
61 60
    public function isActive($item)
62
    {
63
        // Return true if any of the verification tests is met.
64
65 60
        foreach ($this->tests as $prop => $testFunc) {
66 60
            if (isset($item[$prop]) && $testFunc($item[$prop])) {
67 46
                return true;
68
            }
69
        }
70
71
        // Otherwise, returns false.
72
73 40
        return false;
74
    }
75
76
    /**
77
     * Checks if an array of items contains an active item.
78
     *
79
     * @param array $items The items to check
80
     * @return bool
81
     */
82 16
    protected function containsActive($items)
83
    {
84 16
        foreach ($items as $item) {
85 12
            if ($this->isActive($item)) {
86 3
                return true;
87
            }
88
        }
89
90 13
        return false;
91
    }
92
93
    /**
94
     * Checks if an item is active by explicit definition of 'active' state.
95
     *
96
     * @param bool|array $activeDef
97
     * @return bool
98
     */
99 20
    protected function isExplicitActive($activeDef)
100
    {
101
        // If the active definition is a bool, return it.
102
103 20
        if (is_bool($activeDef)) {
104 13
            return $activeDef;
105
        }
106
107
        // Otherwise, check if any of the url patterns that defines the active
108
        // state matches the requested url.
109
110 7
        foreach ($activeDef as $pattern) {
111 7
            if ($this->checkPattern($pattern)) {
112 5
                return true;
113
            }
114
        }
115
116 5
        return false;
117
    }
118
119
    /**
120
     * Checks if an url pattern matches the requested url.
121
     *
122
     * @param string $pattern
123
     * @return bool
124
     */
125 59
    protected function checkPattern($pattern)
126
    {
127
        // First, check if the pattern is a regular expression.
128
129 59
        if (Str::startsWith($pattern, 'regex:')) {
130 1
            $regex = Str::substr($pattern, 6);
131
132 1
            return (bool) preg_match($regex, $this->request->path());
133
        }
134
135
        // If pattern is not a regex, check if the requested url matches the
136
        // absolute path to the given pattern.
137
138 58
        return Str::is($this->url->to($pattern), $this->request->url());
139
    }
140
}
141