NavHelper::_setItemParams()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
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\View\Helper;
17
18
use JBZoo\Utils\FS;
19
use Cake\Utility\Hash;
20
21
/**
22
 * Class NavHelper
23
 *
24
 * @package Core\View\Helper
25
 * @property \Core\View\Helper\UrlHelper $Url
26
 */
27
class NavHelper extends AppHelper
28
{
29
30
    /**
31
     * List of helpers used by this helper.
32
     *
33
     * @var array
34
     */
35
    public $helpers = [
36
        'Url' => ['className' => 'Core.Url']
37
    ];
38
39
    /**
40
     * Hold item params.
41
     *
42
     * @var array
43
     */
44
    protected static $_itemParams = [];
45
46
    /**
47
     * Default menu params.
48
     *
49
     * @var array
50
     */
51
    protected $_default = [
52
        'menuAttr' => [
53
            'class'   => 'menu',
54
            'element' => 'Core.Nav/menu'
55
        ],
56
        'childMenuAttr' => [
57
            'class'   => 'child-menu',
58
            'element' => 'Core.Nav/menu_child'
59
        ],
60
        'itemElement' => 'Core.Nav/item',
61
    ];
62
63
    /**
64
     * Render menu.
65
     *
66
     * @param string $key
67
     * @param array $items
68
     * @param array $options
69
     * @param int $level
70
     * @return string
71
     * @SuppressWarnings(PHPMD.ShortVariable)
72
     */
73
    public function render($key, array $items = [], array $options = [], $level = 1)
74
    {
75
        $i = 0;
76
        $output    = [];
77
        $options   = Hash::merge($this->_default, $options);
78
        $sorted    = Hash::sort($items, '{s}.weight', 'ASC');
79
        $itemCount = count($sorted);
80
81
        foreach ($sorted as $item) {
82
            $i++;
83
            $item = $this->_setFirstLast($i, $itemCount, $item);
84
85
            $children = false;
86
            if (count($item['children']) > 0) {
87
                $children = $this->render($key, $item['children'], $options, $level + 1);
88
            }
89
90
            $itemParams = [
91
                'options'  => $options,
92
                'item'     => $item,
93
                'count'    => $i,
94
                'children' => $children,
95
                'level'    => $level,
96
            ];
97
98
            $this->_setItemParams($itemParams);
99
100
            if (isset($item['callable']) && is_callable($item['callable'])) {
101
                $output[] = call_user_func_array($item['callable'], array_merge(['view' => $this->_View], $itemParams));
102
            } else {
103
                $output[] = $this->_View->element($options['itemElement'], $itemParams);
104
            }
105
        }
106
107
        $element = $this->_getCurrentMenuElement($options, $level);
108
109
        return $this->_View->element($element, [
110
            'content' => $output,
111
            'options' => $options,
112
        ]);
113
    }
114
115
    /**
116
     * Get current menu element.
117
     *
118
     * @param array $options
119
     * @param int $level
120
     * @return string
121
     */
122
    protected function _getCurrentMenuElement(array $options = [], $level = 1)
123
    {
124
        if ($level > 1) {
125
            $levelElement = $this->_getLevelElement($options, $level);
126
            if ($this->_View->elementExists($levelElement)) {
127
                return $levelElement;
128
            }
129
130
            return $options['childMenuAttr']['element'];
131
        }
132
133
        return $options['menuAttr']['element'];
134
    }
135
136
    /**
137
     * Get current menu level element.
138
     *
139
     * @param array $options
140
     * @param int $level
141
     * @return string
142
     */
143
    protected function _getLevelElement(array $options, $level)
144
    {
145
        $levelElement = 'menu_child_' . $level;
146
        $element      = $options['childMenuAttr']['element'];
147
148
        list($plugin, $path) = $this->_View->pluginSplit($element);
149
        $path    = FS::clean($path, '/');
150
        $details = explode('/', $path);
151
        array_pop($details);
152
153
        $path = implode('/', $details);
154
155
        return $plugin . '.' . $path . '/' . $levelElement;
156
    }
157
158
    /**
159
     * Setup first last item params.
160
     *
161
     * @param int $i
162
     * @param int $itemCount
163
     * @param array $item
164
     * @return array
165
     * @SuppressWarnings(PHPMD.ShortVariable)
166
     */
167
    protected function _setFirstLast($i, $itemCount, array $item = [])
168
    {
169
        $item = array_merge(['last' => false, 'first' => false], $item);
170
        if ($i == 1) {
171
            $item['first'] = true;
172
        }
173
174
        if ($i == $itemCount) {
175
            $item['last'] = true;
176
        }
177
178
        return $item;
179
    }
180
181
    /**
182
     * Get default li attributes.
183
     *
184
     * @return array
185
     */
186
    public function getLiAttr()
187
    {
188
        $params = self::$_itemParams;
189
        $attr   = ['class' => 'li-item'];
190
191
        if (isset($params['item']['liClass'])) {
192
            $attr = $this->addClass($attr, $params['item']['liClass']);
193
        }
194
195
        if ($params['item']['last']) {
196
            $attr = $this->addClass($attr, 'last');
197
        }
198
199
        if ($params['item']['first']) {
200
            $attr = $this->addClass($attr, 'first');
201
        }
202
203
        return $this->_setActive($attr);
204
    }
205
206
    /**
207
     * Set active item link.
208
     *
209
     * @param array $attr
210
     * @return array
211
     */
212
    protected function _setActive(array $attr = [])
213
    {
214
        if ($this->Url->build(self::$_itemParams['item']['url']) == env('REQUEST_URI')) {
215
            $attr = $this->addClass($attr, 'active');
216
        }
217
218
        return $attr;
219
    }
220
221
    /**
222
     * Set item params fo hold.
223
     *
224
     * @param array $params
225
     * @return void
226
     */
227
    protected function _setItemParams(array $params = [])
228
    {
229
        self::$_itemParams = $params;
230
    }
231
}
232