0)); $menu_names = array(); foreach ($menus as $id => $title) { list($menu_name, $mlid) = explode(':', $id); // Store the title each menu for reference. if ($mlid == '0') { $menu_names[$menu_name] = $title; } else { $link = menu_link_load($mlid); $identifier = $link['link_path']; $root_menu = $menu_names[$menu_name]; while (isset($options[$root_menu][$menu_name . ':' . $identifier])) { $identifier .= "'"; } $options[$root_menu][$menu_name . ':' . $identifier] = $title; } } } $menu_count = count($options, COUNT_RECURSIVE); return array( '#title' => $this->title, '#description' => $this->description, '#options' => $options, '#type' => 'select', '#multiple' => TRUE, '#size' => $menu_count > 20 ? 20 : $menu_count, '#default_value' => $this->fetch_from_context($context), ); } /** * Override of options_form_submit(). * Trim any identifier padding for non-unique path menu items. */ function options_form_submit($values) { $trimmed = array(); foreach ($values as $value) { $value = trim($value, "'"); $trimmed[] = $value; } return $trimmed; } /** * Overrides parent function to include legacy handling for old format of just storing a single path. */ function fetch_from_context($context) { $values = parent::fetch_from_context($context); // Legacy - convert single string value to an array with a preferred menu if (is_string($values)) { $menu = menu_link_get_preferred($values); if (!$menu) { return array(); } return array($menu['menu_name'] . ':' . $menu['link_path']); } return $values; } /** * Provide active trail in all menus in which our path appears. */ function execute(&$vars = NULL) { $menu_names = menu_get_active_menu_names(); $active_paths = $this->get_active_paths(); foreach ($menu_names as $menu_name) { if (isset($active_paths[$menu_name])) { foreach($active_paths[$menu_name] as $path) { if ($link = menu_link_get_preferred($path, $menu_name)) { $this->set_active_trail_from_link($link); return; } } } } // None of the links can be found in their preferred menus. Instead we just try to find any of the paths in any // menu. Note that the preferred menu names list is still used but not always honoured. // We hope to not have to fall into this section as we could end up doing rather a lot of lookups. foreach ($active_paths as $menu_name => $paths) { foreach($paths as $path) { if ($link = menu_link_get_preferred($path)) { $this->set_active_trail_from_link($link); return; } } } } /** * Helper function to build and set the active trail from a menu link. * * @param $item * A menu link item. */ function set_active_trail_from_link($item) { menu_tree_set_path($item['menu_name'], $item['link_path']); $trail = array(); while($item) { array_unshift($trail, $item); $item = menu_link_load($item['plid']); } array_unshift($trail, array( 'title' => t('Home'), 'href' => '', 'link_path' => '', 'localized_options' => array(), 'type' => 0, )); menu_set_active_trail($trail); } /** * Helper function to return the list of currently active paths. * * The paths are grouped by menu name. */ function get_active_paths() { $active_paths = array(); foreach ($this->get_contexts() as $context) { $paths = $this->fetch_from_context($context); $active_paths = array_merge($active_paths, $paths); } $by_menu_name = array(); foreach ($active_paths as $id) { list($menu_name, $path) = explode(':', $id); $by_menu_name[$menu_name][] = $path; } return $by_menu_name; } }