1: <?php
2: /**
3: * Elgg Menu Item
4: *
5: * To create a menu item that is not a link, pass false for $href.
6: *
7: * @package Elgg.Core
8: * @subpackage Navigation
9: * @since 1.8.0
10: */
11: class ElggMenuItem {
12:
13: /**
14: * @var array Non-rendered data about the menu item
15: */
16: protected $data = array(
17: // string Identifier of the menu
18: 'name' => '',
19:
20: // array Page contexts this menu item should appear on
21: 'contexts' => array('all'),
22:
23: // string Menu section identifier
24: 'section' => 'default',
25:
26: // int Smaller priorities float to the top
27: 'priority' => 100,
28:
29: // bool Is this the currently selected menu item
30: 'selected' => false,
31:
32: // string Identifier of this item's parent
33: 'parent_name' => '',
34:
35: // ElggMenuItem The parent object or null
36: 'parent' => null,
37:
38: // array Array of children objects or empty array
39: 'children' => array(),
40:
41: // array Classes to apply to the li tag
42: 'itemClass' => array(),
43:
44: // array Classes to apply to the anchor tag
45: 'linkClass' => array(),
46: );
47:
48: /**
49: * @var string The menu display string
50: */
51: protected $text;
52:
53: /**
54: * @var string The menu url
55: */
56: protected $href = null;
57:
58: /**
59: * @var string Tooltip
60: */
61: protected $title = false;
62:
63: /**
64: * @var string The string to display if link is clicked
65: */
66: protected $confirm = '';
67:
68:
69: /**
70: * ElggMenuItem constructor
71: *
72: * @param string $name Identifier of the menu item
73: * @param string $text Display text of the menu item
74: * @param string $href URL of the menu item (false if not a link)
75: */
76: public function __construct($name, $text, $href) {
77: //$this->name = $name;
78: $this->text = $text;
79: if ($href) {
80: $this->href = elgg_normalize_url($href);
81: } else {
82: $this->href = $href;
83: }
84:
85: $this->data['name'] = $name;
86: }
87:
88: /**
89: * ElggMenuItem factory method
90: *
91: * This static method creates an ElggMenuItem from an associative array.
92: * Required keys are name, text, and href.
93: *
94: * @param array $options Option array of key value pairs
95: *
96: * @return ElggMenuItem or NULL on error
97: */
98: public static function factory($options) {
99: if (!isset($options['name']) || !isset($options['text'])) {
100: return NULL;
101: }
102: if (!isset($options['href'])) {
103: $options['href'] = '';
104: }
105:
106: $item = new ElggMenuItem($options['name'], $options['text'], $options['href']);
107: unset($options['name']);
108: unset($options['text']);
109: unset($options['href']);
110:
111: // special catch in case someone uses context rather than contexts
112: if (isset($options['context'])) {
113: $options['contexts'] = $options['context'];
114: unset($options['context']);
115: }
116:
117: // make sure contexts is set correctly
118: if (isset($options['contexts'])) {
119: $item->setContext($options['contexts']);
120: unset($options['contexts']);
121: }
122:
123: if (isset($options['link_class'])) {
124: $item->setLinkClass($options['link_class']);
125: unset($options['link_class']);
126: }
127:
128: if (isset($options['item_class'])) {
129: $item->setItemClass($options['item_class']);
130: unset($options['item_class']);
131: }
132:
133: if (isset($options['data']) && is_array($options['data'])) {
134: $item->setData($options['data']);
135: unset($options['data']);
136: }
137:
138: foreach ($options as $key => $value) {
139: if (isset($item->data[$key])) {
140: $item->data[$key] = $value;
141: } else {
142: $item->$key = $value;
143: }
144: }
145:
146: return $item;
147: }
148:
149: /**
150: * Set a data key/value pair or a set of key/value pairs
151: *
152: * This method allows storage of arbitrary data with this menu item. The
153: * data can be used for sorting, custom rendering, or any other use.
154: *
155: * @param mixed $key String key or an associative array of key/value pairs
156: * @param mixed $value The value if $key is a string
157: * @return void
158: */
159: public function setData($key, $value = null) {
160: if (is_array($key)) {
161: $this->data += $key;
162: } else {
163: $this->data[$key] = $value;
164: }
165: }
166:
167: /**
168: * Get stored data
169: *
170: * @param string $key The key for the requested key/value pair
171: * @return mixed
172: */
173: public function getData($key) {
174: if (isset($this->data[$key])) {
175: return $this->data[$key];
176: } else {
177: return null;
178: }
179: }
180:
181: /**
182: * Set the identifier of the menu item
183: *
184: * @param string $name Unique identifier
185: * @return void
186: */
187: public function setName($name) {
188: $this->data['name'] = $name;
189: }
190:
191: /**
192: * Get the identifier of the menu item
193: *
194: * @return string
195: */
196: public function getName() {
197: return $this->data['name'];
198: }
199:
200: /**
201: * Set the display text of the menu item
202: *
203: * @param string $text The display text
204: * @return void
205: */
206: public function setText($text) {
207: $this->text = $text;
208: }
209:
210: /**
211: * Get the display text of the menu item
212: *
213: * @return string
214: */
215: public function getText() {
216: return $this->text;
217: }
218:
219: /**
220: * Set the URL of the menu item
221: *
222: * @param string $href URL or false if not a link
223: * @return void
224: */
225: public function setHref($href) {
226: $this->href = $href;
227: }
228:
229: /**
230: * Get the URL of the menu item
231: *
232: * @return string
233: */
234: public function getHref() {
235: return $this->href;
236: }
237:
238: /**
239: * Set the contexts that this menu item is available for
240: *
241: * @param array $contexts An array of context strings
242: * @return void
243: */
244: public function setContext($contexts) {
245: if (is_string($contexts)) {
246: $contexts = array($contexts);
247: }
248: $this->data['contexts'] = $contexts;
249: }
250:
251: /**
252: * Get an array of context strings
253: *
254: * @return array
255: */
256: public function getContext() {
257: return $this->data['contexts'];
258: }
259:
260: /**
261: * Should this menu item be used given the current context
262: *
263: * @param string $context A context string (default is empty string for
264: * current context stack).
265: * @return bool
266: */
267: public function inContext($context = '') {
268: if ($context) {
269: return in_array($context, $this->data['contexts']);
270: }
271:
272: if (in_array('all', $this->data['contexts'])) {
273: return true;
274: }
275:
276: foreach ($this->data['contexts'] as $context) {
277: if (elgg_in_context($context)) {
278: return true;
279: }
280: }
281: return false;
282: }
283:
284: /**
285: * Set the selected flag
286: *
287: * @param bool $state Selected state (default is true)
288: * @return void
289: */
290: public function setSelected($state = true) {
291: $this->data['selected'] = $state;
292: }
293:
294: /**
295: * Get selected state
296: *
297: * @return bool
298: */
299: public function getSelected() {
300: return $this->data['selected'];
301: }
302:
303: /**
304: * Set the tool tip text
305: *
306: * @param string $text The text of the tool tip
307: * @return void
308: */
309: public function setTooltip($text) {
310: $this->title = $text;
311: }
312:
313: /**
314: * Get the tool tip text
315: *
316: * @return string
317: */
318: public function getTooltip() {
319: return $this->title;
320: }
321:
322: /**
323: * Set the confirm text shown when link is clicked
324: *
325: * @param string $text The text to show
326: * @return void
327: */
328: public function setConfirmText($text) {
329: $this->confirm = $text;
330: }
331:
332: /**
333: * Get the confirm text
334: *
335: * @return string
336: */
337: public function getConfirmText() {
338: return $this->confirm;
339: }
340:
341: /**
342: * Set the anchor class
343: *
344: * @param mixed $class An array of class names, or a single string class name.
345: * @return void
346: */
347: public function setLinkClass($class) {
348: if (!is_array($class)) {
349: $this->data['linkClass'] = array($class);
350: } else {
351: $this->data['linkClass'] = $class;
352: }
353: }
354:
355: /**
356: * Get the anchor classes as text
357: *
358: * @return string
359: */
360: public function getLinkClass() {
361: return implode(' ', $this->data['linkClass']);
362: }
363:
364: /**
365: * Add a link class
366: *
367: * @param mixed $class An array of class names, or a single string class name.
368: * @return void
369: */
370: public function addLinkClass($class) {
371: if (!is_array($class)) {
372: $this->data['linkClass'][] = $class;
373: } else {
374: $this->data['linkClass'] += $class;
375: }
376: }
377:
378: /**
379: * Set the li classes
380: *
381: * @param mixed $class An array of class names, or a single string class name.
382: * @return void
383: */
384: public function setItemClass($class) {
385: if (!is_array($class)) {
386: $this->data['itemClass'] = array($class);
387: } else {
388: $this->data['itemClass'] = $class;
389: }
390: }
391:
392: /**
393: * Get the li classes as text
394: *
395: * @return string
396: */
397: public function getItemClass() {
398: // allow people to specify name with underscores and colons
399: $name = strtolower($this->getName());
400: $name = str_replace('_', '-', $name);
401: $name = str_replace(':', '-', $name);
402: $name = str_replace(' ', '-', $name);
403:
404: $class = implode(' ', $this->data['itemClass']);
405: if ($class) {
406: return "elgg-menu-item-$name $class";
407: } else {
408: return "elgg-menu-item-$name";
409: }
410: }
411:
412: /**
413: * Set the priority of the menu item
414: *
415: * @param int $priority The smaller numbers mean higher priority (1 before 100)
416: * @return void
417: * @deprecated
418: */
419: public function setWeight($priority) {
420: $this->data['priority'] = $priority;
421: }
422:
423: /**
424: * Get the priority of the menu item
425: *
426: * @return int
427: * @deprecated
428: */
429: public function getWeight() {
430: return $this->data['priority'];
431: }
432:
433: /**
434: * Set the priority of the menu item
435: *
436: * @param int $priority The smaller numbers mean higher priority (1 before 100)
437: * @return void
438: */
439: public function setPriority($priority) {
440: $this->data['priority'] = $priority;
441: }
442:
443: /**
444: * Get the priority of the menu item
445: *
446: * @return int
447: */
448: public function getPriority() {
449: return $this->data['priority'];
450: }
451:
452: /**
453: * Set the section identifier
454: *
455: * @param string $section The identifier of the section
456: * @return void
457: */
458: public function setSection($section) {
459: $this->data['section'] = $section;
460: }
461:
462: /**
463: * Get the section identifier
464: *
465: * @return string
466: */
467: public function getSection() {
468: return $this->data['section'];
469: }
470:
471: /**
472: * Set the parent identifier
473: *
474: * @param string $name The identifier of the parent ElggMenuItem
475: * @return void
476: */
477: public function setParentName($name) {
478: $this->data['parent_name'] = $name;
479: }
480:
481: /**
482: * Get the parent identifier
483: *
484: * @return string
485: */
486: public function getParentName() {
487: return $this->data['parent_name'];
488: }
489:
490: /**
491: * Set the parent menu item
492: *
493: * @param ElggMenuItem $parent The parent of this menu item
494: * @return void
495: */
496: public function setParent($parent) {
497: $this->data['parent'] = $parent;
498: }
499:
500: /**
501: * Get the parent menu item
502: *
503: * @return ElggMenuItem or null
504: */
505: public function getParent() {
506: return $this->data['parent'];
507: }
508:
509: /**
510: * Add a child menu item
511: *
512: * @param ElggMenuItem $item A child menu item
513: * @return void
514: */
515: public function addChild($item) {
516: $this->data['children'][] = $item;
517: }
518:
519: /**
520: * Set the menu item's children
521: *
522: * @param array $children Array of ElggMenuItems
523: * @return void
524: */
525: public function setChildren($children) {
526: $this->data['children'] = $children;
527: }
528:
529: /**
530: * Get the children menu items
531: *
532: * @return array
533: */
534: public function getChildren() {
535: return $this->data['children'];
536: }
537:
538: /**
539: * Sort the children
540: *
541: * @param string $sortFunction A function that is passed to usort()
542: * @return void
543: */
544: public function sortChildren($sortFunction) {
545: foreach ($this->data['children'] as $key => $node) {
546: $this->data['children'][$key]->data['original_order'] = $key;
547: }
548: usort($this->data['children'], $sortFunction);
549: }
550:
551: /**
552: * Get the menu item content (usually a link)
553: *
554: * @param array $vars Options to pass to output/url if a link
555: * @return string
556: * @todo View code in a model. How do we feel about that?
557: */
558: public function getContent(array $vars = array()) {
559:
560: if ($this->href === false) {
561: return $this->text;
562: }
563:
564: $defaults = get_object_vars($this);
565: unset($defaults['data']);
566:
567: $vars += $defaults;
568:
569: if ($this->data['linkClass']) {
570: if (isset($vars['class'])) {
571: $vars['class'] = $vars['class'] . ' ' . $this->getLinkClass();
572: } else {
573: $vars['class'] = $this->getLinkClass();
574: }
575: }
576:
577: if (!isset($vars['rel']) && !isset($vars['is_trusted'])) {
578: $vars['is_trusted'] = true;
579: }
580:
581: if ($this->confirm) {
582: $vars['confirm'] = $this->confirm;
583: return elgg_view('output/confirmlink', $vars);
584: } else {
585: unset($vars['confirm']);
586: }
587:
588: return elgg_view('output/url', $vars);
589: }
590: }
591: