context_reaction_menu.inc 4.2 KB

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