1: <?php
2: namespace Menu\Items;
3:
4: use HtmlObject\Element;
5: use HtmlObject\Traits\Tag;
6:
7: use Menu\Menu;
8: use Menu\Traits\Content;
9: use Menu\Traits\MenuObject;
10: use Menu\MenuHandler;
11:
12: use Underscore\Methods\ArraysMethods;
13:
14: 15: 16:
17: class Item extends MenuObject
18: {
19: 20: 21: 22: 23:
24: protected $patterns = array();
25:
26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36: public function __construct(ItemList $parent, Tag $value, $children = null, $element = null, $beforeContent = null, $afterContent = null)
37: {
38: $this->parent = $parent;
39: $this->children = is_null($children) ? new ItemList() : $children;
40: $this->element = $element;
41: $this->beforeContent = $beforeContent;
42: $this->afterContent = $afterContent;
43:
44:
45: $this->value = $value->setParent($this);
46: }
47:
48: 49: 50: 51: 52: 53: 54:
55: public function setActivePatterns($pattern, $name = null)
56: {
57: if (!$name) $name = sizeof($this->patterns);
58: $this->patterns[$name] = $pattern;
59: }
60:
61: 62: 63: 64: 65:
66: public function stop()
67: {
68: return $this->getParent();
69: }
70:
71: 72: 73: 74: 75:
76: public function getContent()
77: {
78: return $this->value;
79: }
80:
81: 82: 83: 84: 85:
86: public function setBeforeContent($value)
87: {
88: $this->beforeContent = $value;
89: return $this;
90: }
91:
92: 93: 94: 95: 96:
97: public function setAfterContent($value)
98: {
99: $this->beforeContent = $value;
100: return $this;
101: }
102:
103: 104: 105: 106: 107:
108: public function setElement($element = null)
109: {
110: $this->setOption('item.element', $element);
111:
112: return $this;
113: }
114:
115: 116: 117: 118: 119:
120: public function getElement()
121: {
122: if(is_null($this->element))
123: {
124: return $this->getOption('item.element');
125: }
126:
127: return $this->element;
128: }
129:
130: 131: 132: 133: 134: 135: 136:
137: public function render($depth = 0)
138: {
139:
140: $value = is_null($this->beforeContent) ? '' : $this->beforeContent;
141: $value .= $this->value->render();
142: $value .= is_null($this->afterContent) ? '' : $this->afterContent;
143:
144: $this->addActiveClasses();
145:
146:
147: if ($this->hasChildren()) {
148: $value .= $this->children->render($depth);
149: }
150:
151:
152: $element = $this->getElement();
153: if ($element) $value = Element::create($element, $value, $this->attributes)->render();
154: return html_entity_decode($value, ENT_QUOTES, 'UTF-8');
155: }
156:
157:
158:
159:
160:
161: 162: 163: 164: 165:
166: public function isActive()
167: {
168: if( ! $this->value->isLink()) {
169: return false;
170: }
171:
172: return
173: trim($this->getUrl(), '/') == trim($this->getRequest()->getPathInfo(), '/') or
174: $this->getUrl() == $this->getRequest()->fullUrl() or
175: $this->getUrl() == $this->getRequest()->url() or
176: $this->hasActivePatterns();
177: }
178:
179: public function hasChildren()
180: {
181: return count($this->children->getChildren()) > 0;
182: }
183:
184: 185: 186: 187: 188:
189: protected function hasActivePatterns()
190: {
191: foreach ($this->patterns as $pattern) {
192: $path = $this->getRequest()->getPathInfo();
193:
194: if (is_array($pattern)) {
195: foreach ($pattern as $p)
196: $isActive = preg_match('/'.$p.'/i', $path);
197: } else {
198: $isActive = preg_match('/'.$pattern.'/i', $path);
199: }
200:
201: if($isActive) return true;
202: }
203:
204: return false;
205: }
206:
207: 208: 209: 210: 211:
212: public function hasActiveChild()
213: {
214: if (!$this->hasChildren()) {
215: return false;
216: }
217:
218: foreach ($this->children->getChildren() as $child) {
219: if ($child->isActive()) {
220: return true;
221: }
222:
223: if ($child->hasChildren()) {
224: return $child->hasActiveChild();
225: }
226: }
227:
228: return false;
229: }
230:
231: 232: 233: 234: 235:
236: protected function getUrl()
237: {
238: return $this->value->isLink() ? $this->value->getEvaluatedUrl() : null;
239: }
240:
241:
242:
243:
244:
245: 246: 247:
248: private function addActiveClasses()
249: {
250: if ($this->isActive()) {
251: $this->addClass($this->getOption('item.active_class'));
252: }
253:
254: if ($this->hasActiveChild()) {
255: $this->addClass($this->getOption('item.active_child_class'));
256: }
257: }
258:
259:
260:
261:
262:
263: 264: 265: 266: 267:
268: public function getRequest()
269: {
270: return Menu::getContainer('request');
271: }
272:
273: }
274: