Normalizer::renderLabel()   A
last analyzed

Complexity

Conditions 6
Paths 8

Size

Total Lines 23
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 9
nc 8
nop 5
dl 0
loc 23
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Widgets\Helper;
6
7
use InvalidArgumentException;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Html\Tag\I;
10
use Yiisoft\Html\Tag\Span;
11
12
final class Normalizer
13
{
14
    /**
15
     * Normalize the given array of items for the dropdown.
16
     */
17
    public static function dropdown(array $items): array
18
    {
19
        /**
20
         * @psalm-var array[] $items
21
         * @psalm-suppress RedundantConditionGivenDocblockType
22
         */
23
        foreach ($items as $i => $child) {
24
            if (is_array($child)) {
25
                $items[$i]['label'] = self::renderLabel(
26
                    self::label($child),
27
                    self::icon($child),
28
                    self::iconAttributes($child),
29
                    self::iconClass($child),
30
                    self::iconContainerAttributes($child),
31
                );
32
                $items[$i]['active'] = self::active($child, '', '', false);
33
                $items[$i]['disabled'] = self::disabled($child);
34
                $items[$i]['enclose'] = self::enclose($child);
35
                $items[$i]['headerAttributes'] = self::headerAttributes($child);
36
                $items[$i]['itemContainerAttributes'] = self::itemContainerAttributes($child);
37
                $items[$i]['link'] = self::link($child, '/');
38
                $items[$i]['linkAttributes'] = self::linkAttributes($child);
39
                $items[$i]['toggleAttributes'] = self::toggleAttributes($child);
40
                $items[$i]['visible'] = self::visible($child);
41
42
                if (isset($child['items']) && is_array($child['items'])) {
43
                    $items[$i]['items'] = self::dropdown($child['items']);
44
                } else {
45
                    $items[$i]['items'] = [];
46
                }
47
            }
48
        }
49
50
        return $items;
51
    }
52
53
    /**
54
     * Normalize the given array of items for the menu.
55
     */
56
    public static function menu(
57
        array $items,
58
        string $currentPath,
59
        bool $activateItems,
60
        array $iconContainerAttributes = []
61
    ): array {
62
        /**
63
         * @psalm-var array[] $items
64
         * @psalm-suppress RedundantConditionGivenDocblockType
65
         */
66
        foreach ($items as $i => $child) {
67
            if (is_array($child)) {
68
                if (isset($child['items']) && is_array($child['items'])) {
69
                    $items[$i]['items'] = self::menu(
70
                        $child['items'],
71
                        $currentPath,
72
                        $activateItems,
73
                        $iconContainerAttributes,
74
                    );
75
                } else {
76
                    $items[$i]['link'] = self::link($child);
77
                    $items[$i]['linkAttributes'] = self::linkAttributes($child);
78
                    $items[$i]['active'] = self::active(
79
                        $child,
80
                        $items[$i]['link'],
81
                        $currentPath,
82
                        $activateItems
83
                    );
84
                    $items[$i]['disabled'] = self::disabled($child);
85
                    $items[$i]['visible'] = self::visible($child);
86
                    $items[$i]['label'] = self::renderLabel(
87
                        self::label($child),
88
                        self::icon($child),
89
                        self::iconAttributes($child),
90
                        self::iconClass($child),
91
                        self::iconContainerAttributes($child, $iconContainerAttributes),
92
                    );
93
                }
94
            }
95
        }
96
97
        return $items;
98
    }
99
100
    public static function renderLabel(
101
        string $label,
102
        string $icon,
103
        array $iconAttributes,
104
        string $iconClass,
105
        array $iconContainerAttributes
106
    ): string {
107
        $html = '';
108
109
        if ($iconClass !== '') {
110
            Html::addCssClass($iconAttributes, $iconClass);
111
        }
112
113
        if ($icon !== '' || $iconAttributes !== [] || $iconClass !== '') {
114
            $i = I::tag()->attributes($iconAttributes)->content($icon);
115
            $html = Span::tag()->attributes($iconContainerAttributes)->content($i)->encode(false)->render();
116
        }
117
118
        if ($label !== '') {
119
            $html .= $label;
120
        }
121
122
        return $html;
123
    }
124
125
    private static function active(array $item, string $link, string $currentPath, bool $activateItems): bool
126
    {
127
        if (!array_key_exists('active', $item)) {
128
            return self::isItemActive($link, $currentPath, $activateItems);
129
        }
130
131
        return is_bool($item['active']) ? $item['active'] : false;
132
    }
133
134
    private static function disabled(array $item): bool
135
    {
136
        return array_key_exists('disabled', $item) && is_bool($item['disabled']) ? $item['disabled'] : false;
137
    }
138
139
    private static function enclose(array $item): bool
140
    {
141
        return array_key_exists('enclose', $item) && is_bool($item['enclose']) ? $item['enclose'] : true;
142
    }
143
144
    private static function headerAttributes(array $item): array
145
    {
146
        return array_key_exists('headerAttributes', $item) && is_array($item['headerAttributes'])
147
            ? $item['headerAttributes']
148
            : [];
149
    }
150
151
    private static function icon(array $item): string
152
    {
153
        return array_key_exists('icon', $item) && is_string($item['icon']) ? $item['icon'] : '';
154
    }
155
156
    private static function iconAttributes(array $item): array
157
    {
158
        return array_key_exists('iconAttributes', $item) && is_array($item['iconAttributes'])
159
            ? $item['iconAttributes'] : [];
160
    }
161
162
    private static function iconClass(array $item): string
163
    {
164
        return array_key_exists('iconClass', $item) && is_string($item['iconClass']) ? $item['iconClass'] : '';
165
    }
166
167
    private static function iconContainerAttributes(array $item, array $iconContainerAttributes = []): array
168
    {
169
        return array_key_exists('iconContainerAttributes', $item) && is_array($item['iconContainerAttributes'])
170
            ? $item['iconContainerAttributes'] : $iconContainerAttributes;
171
    }
172
173
    /**
174
     * Checks whether a menu item is active.
175
     *
176
     * This is done by checking match that specified in the `url` option of the menu item.
177
     *
178
     * @param string $link The link of the menu item.
179
     * @param string $currentPath The current path.
180
     * @param bool $activateItems Whether to activate items having no link.
181
     *
182
     * @return bool Whether the menu item is active.
183
     */
184
    private static function isItemActive(string $link, string $currentPath, bool $activateItems): bool
185
    {
186
        return $link === $currentPath && $activateItems;
187
    }
188
189
    private static function itemContainerAttributes(array $item): array
190
    {
191
        return array_key_exists('itemContainerAttributes', $item) && is_array($item['itemContainerAttributes'])
192
            ? $item['itemContainerAttributes'] : [];
193
    }
194
195
    private static function label(array $item): string
196
    {
197
        if (!isset($item['label'])) {
198
            throw new InvalidArgumentException('The "label" option is required.');
199
        }
200
201
        if (!is_string($item['label'])) {
202
            throw new InvalidArgumentException('The "label" option must be a string.');
203
        }
204
205
        if ($item['label'] === '' && !isset($item['icon'])) {
206
            throw new InvalidArgumentException('The "label" cannot be an empty string.');
207
        }
208
209
        /** @var bool */
210
        $encode = $item['encode'] ?? true;
211
212
        return $encode ? Html::encode($item['label']) : $item['label'];
213
    }
214
215
    private static function link(array $item, string $defaultValue = ''): string
216
    {
217
        return array_key_exists('link', $item) && is_string($item['link']) ? $item['link'] : $defaultValue;
218
    }
219
220
    private static function linkAttributes(array $item): array
221
    {
222
        return array_key_exists('linkAttributes', $item) && is_array($item['linkAttributes'])
223
            ? $item['linkAttributes'] : [];
224
    }
225
226
    private static function toggleAttributes(array $item): array
227
    {
228
        return array_key_exists('toggleAttributes', $item) && is_array($item['toggleAttributes'])
229
            ? $item['toggleAttributes'] : [];
230
    }
231
232
    private static function visible(array $item): bool
233
    {
234
        return array_key_exists('visible', $item) && is_bool($item['visible']) ? $item['visible'] : true;
235
    }
236
}
237