context_reaction_menu.inc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. /**
  3. * Expose menu items as context reactions.
  4. */
  5. class context_reaction_menu extends context_reaction {
  6. /**
  7. * Provide a form element that allow the admin to chose a menu item.
  8. */
  9. function options_form($context) {
  10. $options = array("-- " . t('None') . " --");
  11. if (module_exists('menu')) {
  12. $menus = menu_parent_options(menu_get_menus(), array('mlid' => 0));
  13. $menu_names = array();
  14. foreach ($menus as $id => $title) {
  15. list($menu_name, $mlid) = explode(':', $id);
  16. // Store the title each menu for reference.
  17. if ($mlid == '0') {
  18. $menu_names[$menu_name] = $title;
  19. }
  20. else {
  21. $link = menu_link_load($mlid);
  22. $identifier = $link['link_path'];
  23. $root_menu = $menu_names[$menu_name];
  24. while (isset($options[$root_menu][$menu_name . ':' . $identifier])) {
  25. $identifier .= "'";
  26. }
  27. $options[$root_menu][$menu_name . ':' . $identifier] = $title;
  28. }
  29. }
  30. }
  31. $menu_count = count($options, COUNT_RECURSIVE);
  32. return array(
  33. '#title' => $this->title,
  34. '#description' => $this->description,
  35. '#options' => $options,
  36. '#type' => 'select',
  37. '#multiple' => TRUE,
  38. '#size' => $menu_count > 20 ? 20 : $menu_count,
  39. '#default_value' => $this->fetch_from_context($context),
  40. );
  41. }
  42. /**
  43. * Override of options_form_submit().
  44. * Trim any identifier padding for non-unique path menu items.
  45. */
  46. function options_form_submit($values) {
  47. $trimmed = array();
  48. foreach ($values as $value) {
  49. $value = trim($value, "'");
  50. $trimmed[] = $value;
  51. }
  52. return $trimmed;
  53. }
  54. /**
  55. * Overrides parent function to include legacy handling for old format of just storing a single path.
  56. */
  57. function fetch_from_context($context) {
  58. $values = parent::fetch_from_context($context);
  59. // Legacy - convert single string value to an array with a preferred menu
  60. if (is_string($values)) {
  61. $menu = menu_link_get_preferred($values);
  62. if (!$menu) {
  63. return array();
  64. }
  65. return array($menu['menu_name'] . ':' . $menu['link_path']);
  66. }
  67. return $values;
  68. }
  69. /**
  70. * Provide active trail in all menus in which our path appears.
  71. */
  72. function execute(&$vars = NULL) {
  73. $menu_names = menu_get_active_menu_names();
  74. $active_paths = $this->get_active_paths();
  75. foreach ($menu_names as $menu_name) {
  76. if (isset($active_paths[$menu_name])) {
  77. foreach($active_paths[$menu_name] as $path) {
  78. if ($link = menu_link_get_preferred($path, $menu_name)) {
  79. $this->set_active_trail_from_link($link);
  80. return;
  81. }
  82. }
  83. }
  84. }
  85. // None of the links can be found in their preferred menus. Instead we just try to find any of the paths in any
  86. // menu. Note that the preferred menu names list is still used but not always honoured.
  87. // We hope to not have to fall into this section as we could end up doing rather a lot of lookups.
  88. foreach ($active_paths as $menu_name => $paths) {
  89. foreach($paths as $path) {
  90. if ($link = menu_link_get_preferred($path)) {
  91. $this->set_active_trail_from_link($link);
  92. return;
  93. }
  94. }
  95. }
  96. }
  97. /**
  98. * Helper function to build and set the active trail from a menu link.
  99. *
  100. * @param $item
  101. * A menu link item.
  102. */
  103. function set_active_trail_from_link($item) {
  104. menu_tree_set_path($item['menu_name'], $item['link_path']);
  105. $trail = array();
  106. while($item) {
  107. array_unshift($trail, $item);
  108. $item = menu_link_load($item['plid']);
  109. }
  110. array_unshift($trail, array(
  111. 'title' => t('Home'),
  112. 'href' => '<front>',
  113. 'link_path' => '',
  114. 'localized_options' => array(),
  115. 'type' => 0,
  116. ));
  117. menu_set_active_trail($trail);
  118. }
  119. /**
  120. * Helper function to return the list of currently active paths.
  121. *
  122. * The paths are grouped by menu name.
  123. */
  124. function get_active_paths() {
  125. $active_paths = array();
  126. foreach ($this->get_contexts() as $context) {
  127. $paths = $this->fetch_from_context($context);
  128. $active_paths = array_merge($active_paths, $paths);
  129. }
  130. $by_menu_name = array();
  131. foreach ($active_paths as $id) {
  132. list($menu_name, $path) = explode(':', $id);
  133. $by_menu_name[$menu_name][] = $path;
  134. }
  135. return $by_menu_name;
  136. }
  137. }