ElggMenuItem.php 14 KB

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