Completed
Pull Request — master (#1)
by David
01:36
created

MenuItem::findChild()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace TheCodingMachine\CMS\StaticRegistry\Menu;
3
4
/**
5
 * This class represent a menu item.
6
 */
7
class MenuItem {
8
9
    /**
10
     * The text for the menu item
11
     *
12
     * @var string
13
     */
14
    private $label;
15
16
    /**
17
     * The link for the menu (relative to the root url), unless it starts with / or http:// or https:// or # or ?.
18
     *
19
     * @var string|null
20
     */
21
    private $url;
22
23
    /**
24
     * The children menu item of this menu (if any).
25
     *
26
     * @var \SplPriorityQueue|MenuItem[]
27
     */
28
    private $children;
29
30
    /**
31
     * The CSS class for the menu, if any.
32
     *
33
     * @var string
34
     */
35
    private $cssClass;
36
37
    /**
38
     * Whether the menu is in an active state or not.
39
     *
40
     * @var bool
41
     */
42
    private $isActive;
43
44
    /**
45
     * Whether the menu is extended or not.
46
     * This should not have an effect if the menu has no child.
47
     *
48
     * @var bool
49
     */
50
    private $isExtended;
51
52
    /**
53
     * Level of priority used to order the menu items.
54
     *
55
     * @var float
56
     */
57
    private $priority = 0.0;
0 ignored issues
show
introduced by
The private property $priority is not used, and could be removed.
Loading history...
58
59
    /**
60
     * @var bool
61
     */
62
    private $activateBasedOnUrl;
63
64
    /**
65
     * @var bool
66
     */
67
    private $sorted = false;
0 ignored issues
show
introduced by
The private property $sorted is not used, and could be removed.
Loading history...
68
69
    /**
70
     * @param string $label The text for the menu item
71
     * @param string|null $url The link for the menu (relative to the root url), unless it starts with / or http:// or https:// or # or ?.
72
     */
73
    public function __construct(string $label, string $url=null) {
74
        $this->label = $label;
75
        $this->url = $url;
76
        $this->children = new \SplPriorityQueue();
77
    }
78
79
    /**
80
     * Returns the label for the menu item.
81
     * @return string
82
     */
83
    public function getLabel(): string {
84
        return $this->label;
85
    }
86
87
    /**
88
     * Returns the URL for this menu (or null if this menu is not a link).
89
     * @return string|null
90
     */
91
    public function getUrl(): ?string {
92
        return $this->url;
93
    }
94
95
    public function findChild(string $label): ?MenuItem
96
    {
97
        foreach ($this->children as $child) {
98
            if ($child->getLabel() === $label) {
99
                return $child;
100
            }
101
        }
102
        return null;
103
    }
104
105
    /**
106
     * Returns a list of children elements for the menu (if there are some).
107
     *
108
     * @return MenuItem[]
109
     */
110
    public function getChildren(): \SplPriorityQueue {
111
        return $this->children;
112
    }
113
114
    /**
115
     * Adds a menu item as a child of this menu item.
116
     *
117
     * @param MenuItem $menuItem
118
     */
119
    public function addMenuItem(MenuItem $menuItem, float $priority): void {
120
        $this->children->insert($menuItem, $priority);
121
    }
122
123
    /**
124
     * Returns true if the menu is in active state (if we are on the page for this menu).
125
     * @return bool
126
     */
127
    public function isActive(string $rootUrl) {
128
        if ($this->isActive) {
129
            return true;
130
        }
131
132
        if($this->activateBasedOnUrl && $this->url !== null) {
133
            $urlParts = parse_url($_SERVER['REQUEST_URI']);
134
            $menuUrlParts = parse_url($this->getLink($rootUrl));
135
136
            if (isset($menuUrlParts['path'])) {
137
                $menuUrl = $menuUrlParts['path'];
138
            } else {
139
                $menuUrl = '/';
140
            }
141
142
            if (isset($urlParts['path'])) {
143
                $requestUrl = $urlParts['path'];
144
            } else {
145
                $requestUrl = '/';
146
            }
147
148
            if($requestUrl === $menuUrl) {
149
                return true;
150
            }
151
        }
152
153
        return false;
154
    }
155
156
    /**
157
     * Set the active state of the menu.
158
     *
159
     * @param bool $isActive
160
     * @return MenuItem
161
     */
162
    public function setIsActive(bool $isActive): self {
163
        $this->isActive = $isActive;
164
        return $this;
165
    }
166
167
    /**
168
     * Enables the menu item (activates it).
169
     *
170
     */
171
    public function enable(): self {
172
        $this->isActive = true;
173
        return $this;
174
    }
175
176
    /**
177
     * Returns true if the menu should be in extended state (if we can see the children directly).
178
     * @return bool
179
     */
180
    public function isExtended(): bool {
181
        // TODO: is extended if one of the sub menus is active!
182
        return $this->isExtended;
183
    }
184
185
    /**
186
     * Whether the menu is extended or not.
187
     * This should not have an effect if the menu has no child.
188
     *
189
     * @param bool $isExtended
190
     * @return MenuItem
191
     */
192
    public function setIsExtended(bool $isExtended = true): self {
193
        $this->isExtended = $isExtended;
194
        return $this;
195
    }
196
197
    /**
198
     * Returns an optional CSS class to apply to the menu item.
199
     * @return string|null
200
     */
201
    public function getCssClass(): ?string {
202
        return $this->cssClass;
203
    }
204
205
    /**
206
     * An optional CSS class to apply to the menu item.
207
     * Use of this property depends on the menu implementation.
208
     *
209
     * @param string $cssClass
210
     */
211
    public function setCssClass($cssClass) {
212
        $this->cssClass = $cssClass;
213
        return $this;
214
    }
215
216
    /**
217
     * Returns the absolute URL, with parameters if required.
218
     * @return string
219
     */
220
    public function getLink(string $rootUrl) {
221
        if ($this->url === null) {
222
            return null;
223
        }
224
225
        if (strpos($this->url, "/") === 0
226
            || strpos($this->url, "javascript:") === 0
227
            || strpos($this->url, "http://") === 0
228
            || strpos($this->url, "https://") === 0
229
            || strpos($this->url, "?") === 0
230
            || strpos($this->url, "#") === 0) {
231
            return $this->url;
232
        }
233
234
        return $rootUrl.$this->url;
235
    }
236
237
    /**
238
     * If the URL of the current page matches the URL of the link, the link will be considered as "active".
239
     *
240
     * @param bool $activateBasedOnUrl
241
     * @return MenuItem
242
     */
243
    public function setActivateBasedOnUrl(bool $activateBasedOnUrl = true): self {
244
        $this->activateBasedOnUrl = $activateBasedOnUrl;
245
        return $this;
246
    }
247
}
248