Nav::clear()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * CakeCMS Core
4
 *
5
 * This file is part of the of the simple cms based on CakePHP 3.
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @package     Core
10
 * @license     MIT
11
 * @copyright   MIT License http://www.opensource.org/licenses/mit-license.php
12
 * @link        https://github.com/CakeCMS/Core".
13
 * @author      Sergey Kalistratov <[email protected]>
14
 */
15
16
namespace Core;
17
18
use Cake\Log\Log;
19
use Cake\Utility\Hash;
20
use Cake\Utility\Inflector;
21
22
/**
23
 * Class Nav
24
 *
25
 * @package Core
26
 */
27
class Nav
28
{
29
30
    /**
31
     * Current active menu.
32
     *
33
     * @see CroogoNav::activeMenu()
34
     */
35
    protected static $_activeMenu = 'sidebar';
36
37
    /**
38
     * Menu items.
39
     *
40
     * @var array
41
     */
42
    protected static $_items = ['sidebar' => []];
43
44
    /**
45
     * Default params.
46
     *
47
     * @var array
48
     */
49
    protected static $_defaults = [
50
        'icon'           => '',
51
        'title'          => false,
52
        'url'            => '#',
53
        'weight'         => 9999,
54
        'before'         => false,
55
        'after'          => false,
56
        'access'         => [],
57
        'children'       => [],
58
        'htmlAttributes' => [],
59
    ];
60
61
    /**
62
     * Getter/setter for activeMenu
63
     *
64
     * @param null $menu
65
     * @return null|string
66
     */
67
    public static function activeMenu($menu = null)
68
    {
69
        if ($menu === null) {
70
            $activeMenu = self::$_activeMenu;
71
        } else {
72
            $activeMenu = $menu;
73
        }
74
75
        if (!array_key_exists($activeMenu, self::$_items)) {
76
            self::$_items[$activeMenu] = [];
77
        }
78
79
        self::$_activeMenu = $activeMenu;
80
        return $activeMenu;
81
    }
82
83
    /**
84
     * Add a menu item.
85
     *
86
     * @param $menu
87
     * @param $path
88
     * @param array $options
89
     */
90
    public static function add($menu, $path, $options = [])
91
    {
92
        // Juggle argument for backward compatibility
93
        if (is_array($path)) {
94
            $options = $path;
95
            $path    = $menu;
96
            $menu    = self::activeMenu();
97
        } else {
98
            self::activeMenu($menu);
99
        }
100
101
        $pathE  = explode('.', $path);
102
        $pathE  = array_splice($pathE, 0, count($pathE) - 2);
103
        $parent = join('.', $pathE);
104
105
        if (!empty($parent) && !Hash::check(self::$_items[$menu], $parent)) {
106
            $title = Inflector::humanize(end($pathE));
107
            $opt = ['title' => $title];
108
            self::_setupOptions($opt);
109
            self::add($parent, $opt);
110
        }
111
112
        self::_setupOptions($options);
113
        $current = Hash::extract(self::$_items[$menu], $path);
114
115
        if (!empty($current)) {
116
            self::_replace(self::$_items[$menu], $path, $options);
117
        } else {
118
            self::$_items[$menu] = Hash::insert(self::$_items[$menu], $path, $options);
119
        }
120
    }
121
122
    /**
123
     * Clear all menus.
124
     *
125
     * @param string $menu
126
     * @return void
127
     */
128
    public static function clear($menu = 'sidebar')
129
    {
130
        if ($menu) {
131
            self::_clear($menu);
132
        } else {
133
            self::$_items = [];
134
        }
135
    }
136
137
    /**
138
     * Gets default settings for menu items.
139
     *
140
     * @return array
141
     */
142
    public static function getDefaults()
143
    {
144
        return self::$_defaults;
145
    }
146
147
    /**
148
     * Sets or returns menu data in array.
149
     *
150
     * @param string $menu
151
     * @param null $items
152
     * @return array
153
     */
154
    public static function items($menu = 'sidebar', $items = null)
155
    {
156
        if (!is_string($menu)) {
157
            throw new \UnexpectedValueException('Menu id is not a string');
158
        }
159
160
        if (!empty($items)) {
161
            self::$_items[$menu] = $items;
162
        }
163
164
        if (!array_key_exists($menu, self::$_items)) {
165
            Log::error('Invalid menu: ' . $menu);
166
            return [];
167
        }
168
169
        return self::$_items[$menu];
170
    }
171
172
    /**
173
     * Get menus.
174
     *
175
     * @return array
176
     */
177
    public static function menus()
178
    {
179
        return array_keys(self::$_items);
180
    }
181
182
    /**
183
     * Remove a menu item.
184
     *
185
     * @param string $path dot separated path in the array.
186
     * @return void
187
     */
188
    public static function remove($path)
189
    {
190
        self::$_items = Hash::remove(self::$_items, $path);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Cake\Utility\Hash::remove(self::$_items, $path) can be null. However, the property $_items is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
191
    }
192
193
    /**
194
     * Clear menu items.
195
     *
196
     * @param $menu
197
     * @throws \UnexpectedValueException
198
     */
199
    protected static function _clear($menu)
200
    {
201
        if (array_key_exists($menu, self::$_items)) {
202
            self::$_items[$menu] = [];
203
        } else {
204
            throw new \UnexpectedValueException('Invalid menu: ' . $menu);
205
        }
206
    }
207
208
    /**
209
     * Merge $firstArray with $secondArray.
210
     *
211
     * Similar to Hash::merge, except duplicates are removed
212
     * @param array $firstArray
213
     * @param array $secondArray
214
     * @return array
215
     */
216
    protected static function _merge($firstArray, $secondArray)
217
    {
218
        $merged = Hash::merge($firstArray, $secondArray);
219
        foreach ($merged as $key => $val) {
220
            if (is_array($val) && is_int(key($val))) {
221
                $merged[$key] = array_unique($val);
222
            }
223
        }
224
        return $merged;
225
    }
226
227
    /**
228
     * Replace a menu element.
229
     *
230
     * @param array $target pointer to start of array
231
     * @param string $path path to search for in dot separated format
232
     * @param array $options data to replace with
233
     * @return void
234
     */
235
    protected static function _replace(&$target, $path, $options)
236
    {
237
        $pathE    = explode('.', $path);
238
        $path     = array_shift($pathE);
239
        $fragment = join('.', $pathE);
240
241
        if (!empty($pathE)) {
242
            self::_replace($target[$path], $fragment, $options);
243
        } else {
244
            $target[$path] = self::_merge($target[$path], $options);
245
        }
246
    }
247
248
    /**
249
     * Setup options.
250
     *
251
     * @param array $options
252
     * @return void
253
     */
254
    protected static function _setupOptions(&$options)
255
    {
256
        $options = self::_merge(self::$_defaults, $options);
257
        foreach ($options['children'] as &$child) {
258
            self::_setupOptions($child);
259
        }
260
    }
261
}
262