1
|
|
|
<?php
|
2
|
|
|
/**
|
3
|
|
|
* TbBaseMenu class file.
|
4
|
|
|
* @author Christoffer Niska <[email protected]>
|
5
|
|
|
* @copyright Copyright © Christoffer Niska 2012-
|
6
|
|
|
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
7
|
|
|
* @package bootstrap.widgets
|
8
|
|
|
*/
|
9
|
|
|
|
10
|
|
|
Yii::import('zii.widgets.CMenu');
|
11
|
|
|
|
12
|
|
|
abstract class TbBaseMenu extends CMenu
|
13
|
|
|
{
|
14
|
|
|
/**
|
15
|
|
|
* Returns the divider css class.
|
16
|
|
|
* @return string the class name
|
17
|
|
|
*/
|
18
|
|
|
abstract public function getDividerCssClass();
|
19
|
|
|
|
20
|
|
|
/**
|
21
|
|
|
* Returns the dropdown css class.
|
22
|
|
|
* @return string the class name
|
23
|
|
|
*/
|
24
|
|
|
abstract public function getDropdownCssClass();
|
25
|
|
|
|
26
|
|
|
/**
|
27
|
|
|
* Returns whether this is a vertical menu.
|
28
|
|
|
* @return boolean the result
|
29
|
|
|
*/
|
30
|
|
|
abstract public function isVertical();
|
31
|
|
|
|
32
|
|
|
/**
|
33
|
|
|
* Renders the menu items.
|
34
|
|
|
* @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
|
35
|
|
|
* It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
|
36
|
|
|
*/
|
37
|
|
|
protected function renderMenu($items)
|
38
|
|
|
{
|
39
|
|
|
$n = count($items);
|
40
|
|
|
|
41
|
|
|
if($n > 0)
|
42
|
|
|
{
|
43
|
|
|
echo CHtml::openTag('ul', $this->htmlOptions);
|
44
|
|
|
|
45
|
|
|
$count = 0;
|
46
|
|
|
foreach ($items as $item)
|
47
|
|
|
{
|
48
|
|
|
$count++;
|
49
|
|
|
|
50
|
|
|
if (isset($item['divider']))
|
51
|
|
|
echo '<li class="'.$this->getDividerCssClass().'"></li>';
|
52
|
|
|
else
|
53
|
|
|
{
|
54
|
|
|
$options = isset($item['itemOptions']) ? $item['itemOptions'] : array();
|
55
|
|
|
$classes = array();
|
56
|
|
|
|
57
|
|
|
if ($item['active'] && $this->activeCssClass != '')
|
58
|
|
|
$classes[] = $this->activeCssClass;
|
59
|
|
|
|
60
|
|
|
if ($count === 1 && $this->firstItemCssClass !== null)
|
61
|
|
|
$classes[] = $this->firstItemCssClass;
|
62
|
|
|
|
63
|
|
|
if ($count === $n && $this->lastItemCssClass !== null)
|
64
|
|
|
$classes[] = $this->lastItemCssClass;
|
65
|
|
|
|
66
|
|
|
if ($this->itemCssClass !== null)
|
67
|
|
|
$classes[] = $this->itemCssClass;
|
68
|
|
|
|
69
|
|
|
if (isset($item['items']))
|
70
|
|
|
$classes[] = $this->getDropdownCssClass();
|
71
|
|
|
|
72
|
|
|
if (isset($item['disabled']))
|
73
|
|
|
$classes[] = 'disabled';
|
74
|
|
|
|
75
|
|
|
if (!empty($classes))
|
76
|
|
|
{
|
77
|
|
|
$classes = implode(' ', $classes);
|
78
|
|
|
if (!empty($options['class']))
|
79
|
|
|
$options['class'] .= ' '.$classes;
|
80
|
|
|
else
|
81
|
|
|
$options['class'] = $classes;
|
82
|
|
|
}
|
83
|
|
|
|
84
|
|
|
echo CHtml::openTag('li', $options);
|
85
|
|
|
|
86
|
|
|
$menu = $this->renderMenuItem($item);
|
87
|
|
|
|
88
|
|
|
if (isset($this->itemTemplate) || isset($item['template']))
|
89
|
|
|
{
|
90
|
|
|
$template = isset($item['template']) ? $item['template'] : $this->itemTemplate;
|
91
|
|
|
echo strtr($template, array('{menu}' => $menu));
|
92
|
|
|
}
|
93
|
|
|
else
|
94
|
|
|
echo $menu;
|
95
|
|
|
|
96
|
|
|
if (isset($item['items']) && !empty($item['items']))
|
97
|
|
|
{
|
98
|
|
|
$this->controller->widget('bootstrap.widgets.TbDropdown', array(
|
99
|
|
|
'encodeLabel'=>$this->encodeLabel,
|
100
|
|
|
'htmlOptions'=>isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions,
|
101
|
|
|
'items'=>$item['items'],
|
102
|
|
|
));
|
103
|
|
|
}
|
104
|
|
|
|
105
|
|
|
echo '</li>';
|
106
|
|
|
}
|
107
|
|
|
}
|
108
|
|
|
|
109
|
|
|
echo '</ul>';
|
110
|
|
|
}
|
111
|
|
|
}
|
112
|
|
|
|
113
|
|
|
/**
|
114
|
|
|
* Renders the content of a menu item.
|
115
|
|
|
* Note that the container and the sub-menus are not rendered here.
|
116
|
|
|
* @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
|
117
|
|
|
* @return string the rendered item
|
118
|
|
|
*/
|
119
|
|
|
protected function renderMenuItem($item)
|
120
|
|
|
{
|
121
|
|
View Code Duplication |
if (isset($item['icon']))
|
|
|
|
|
122
|
|
|
{
|
123
|
|
|
if (strpos($item['icon'], 'icon') === false)
|
124
|
|
|
{
|
125
|
|
|
$pieces = explode(' ', $item['icon']);
|
126
|
|
|
$item['icon'] = 'icon-'.implode(' icon-', $pieces);
|
127
|
|
|
}
|
128
|
|
|
|
129
|
|
|
$item['label'] = '<i class="'.$item['icon'].'"></i> '.$item['label'];
|
130
|
|
|
}
|
131
|
|
|
|
132
|
|
|
if (!isset($item['linkOptions']))
|
133
|
|
|
$item['linkOptions'] = array();
|
134
|
|
|
|
135
|
|
|
if (isset($item['items']) && !empty($item['items']))
|
136
|
|
|
{
|
137
|
|
|
$item['url'] = '#';
|
138
|
|
|
|
139
|
|
|
if (isset($item['linkOptions']['class']))
|
140
|
|
|
$item['linkOptions']['class'] .= ' dropdown-toggle';
|
141
|
|
|
else
|
142
|
|
|
$item['linkOptions']['class'] = 'dropdown-toggle';
|
143
|
|
|
|
144
|
|
|
$item['linkOptions']['data-toggle'] = 'dropdown';
|
145
|
|
|
$item['label'] .= ' <span class="caret"></span>';
|
146
|
|
|
}
|
147
|
|
|
|
148
|
|
View Code Duplication |
if (isset($item['url']))
|
|
|
|
|
149
|
|
|
return CHtml::link($item['label'], $item['url'], $item['linkOptions']);
|
150
|
|
|
else
|
151
|
|
|
return $item['label'];
|
152
|
|
|
}
|
153
|
|
|
|
154
|
|
|
/**
|
155
|
|
|
* Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
|
156
|
|
|
* @param array $items the items to be normalized.
|
157
|
|
|
* @param string $route the route of the current request.
|
158
|
|
|
* @param boolean $active whether there is an active child menu item.
|
159
|
|
|
* @return array the normalized menu items
|
160
|
|
|
*/
|
161
|
|
|
protected function normalizeItems($items, $route, &$active)
|
162
|
|
|
{
|
163
|
|
|
foreach ($items as $i => $item)
|
164
|
|
|
{
|
165
|
|
|
if (!is_array($item))
|
166
|
|
|
$item = array('divider'=>true);
|
167
|
|
|
else
|
168
|
|
|
{
|
169
|
|
|
if (!isset($item['itemOptions']))
|
170
|
|
|
$item['itemOptions'] = array();
|
171
|
|
|
|
172
|
|
|
$classes = array();
|
173
|
|
|
|
174
|
|
|
if (!isset($item['url']) && !isset($item['items']) && $this->isVertical())
|
175
|
|
|
{
|
176
|
|
|
$item['header'] = true;
|
177
|
|
|
$classes[] = 'nav-header';
|
178
|
|
|
}
|
179
|
|
|
|
180
|
|
View Code Duplication |
if (!empty($classes))
|
|
|
|
|
181
|
|
|
{
|
182
|
|
|
$classes = implode($classes, ' ');
|
183
|
|
|
if (isset($item['itemOptions']['class']))
|
184
|
|
|
$item['itemOptions']['class'] .= ' '.$classes;
|
185
|
|
|
else
|
186
|
|
|
$item['itemOptions']['class'] = $classes;
|
187
|
|
|
}
|
188
|
|
|
}
|
189
|
|
|
|
190
|
|
|
$items[$i] = $item;
|
191
|
|
|
}
|
192
|
|
|
|
193
|
|
|
return parent::normalizeItems($items, $route, $active);
|
194
|
|
|
}
|
195
|
|
|
}
|
196
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.