'] = array( 'page callback' => 'drupal_not_found', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_permission(). */ function menu_views_permission() { return array( 'administer menu views' => array( 'title' => t('Administer menu views'), 'description' => t('Allows administrators to attach views to individual menu items and alter the view\'s configuration.'), ), ); } /** * Implements hook_theme_registry_alter(). * Intercepts theme_menu_link(). */ function menu_views_theme_registry_alter(&$registry) { // Save previous value from registry in case another module/theme overwrites theme_menu_link() as well. $registry['menu_views_menu_link_default'] = $registry['menu_link']; $registry['menu_link']['function'] = 'menu_views_menu_link'; // Provide Superfish support. if (isset($registry['superfish_menu_item_link'])) { $registry['menu_views_superfish_menu_item_link_default'] = $registry['superfish_menu_item_link']; $registry['superfish_menu_item_link']['function'] = 'menu_views_superfish_menu_item_link'; } } /** * Implements theme_menu_link(). * Overrides default theming function to intercept views. */ function menu_views_menu_link(array $variables) { // Only intercept if this menu link is a view. if (isset($variables['element']) && $view = _menu_views_replace_menu_item($variables['element'])) { return '' . $view . "\n"; } // Otherwise, use the default theming function. return theme('menu_views_menu_link_default', $variables); } /** * Implements theme_superfish_menu_item_link(). * Overrides default theming function to intercept views. */ function menu_views_superfish_menu_item_link(array $variables) { // Only intercept if this menu item link is a view. if (isset($variables['menu_item']['link']) && $view = _menu_views_replace_menu_item($variables['menu_item']['link'])) { return ''; } // Otherwise, use the default theming function. return theme('menu_views_superfish_menu_item_link_default', $variables); } function _menu_views_replace_menu_item($element) { $output = FALSE; // Only process menu links that are not on admin pages (see: http://drupal.org/node/1790444). if (!path_is_admin(current_path())) { $item = _menu_views_item($element); if ($item['type'] == 'view' && $item['view']['name'] && $item['view']['display']) { $element['#attributes']['class'][] = 'menu-views'; if ($view = views_get_view($item['view']['name'])) { if ($view->access($item['view']['display']) && $view->set_display($item['view']['display'])) { $output = ''; $view->set_arguments(explode('/', _menu_views_tokenize_arguments($item))); // Provide title options for the view. if ((bool)$item['view']['settings']['title']) { $title = $item['view']['settings']['title_override']; if (empty($title)) { $title = $view->get_title(); } if (!empty($title)) { $wrapper = $item['view']['settings']['title_wrapper']; if ($wrapper === '0') { $wrapper = FALSE; } elseif ($wrapper === '') { $wrapper = 'h3'; } if ($wrapper) { $output .= '<' . $wrapper . (!empty($item['view']['settings']['title_classes']) ? ' class="' . $item['view']['settings']['title_classes'] . '"' : '') . '>'; } $output .= $title; if ($wrapper) { $output .= ''; } } } $output .= $view->preview(); } } } } return $output; } function _menu_views_item(&$element = array(), &$form_state = array()) { // Default values. $item = $default = array( 'mlid' => 0, 'type' => 'link', 'tree' => FALSE, 'original_path' => '', 'view' => array( 'name' => FALSE, 'display' => FALSE, 'arguments' => '', 'settings' => array( 'title' => FALSE, 'title_wrapper' => '', 'title_classes' => '', 'title_override' => '', ), ), ); $provided = FALSE; // Attempt to load the menu view element for a link. if (isset($element['menu_views'])) { $provided = &$element['menu_views']; } if (!$provided && isset($element['localized_options']['menu_views'])) { $provided = &$element['localized_options']['menu_views']; } if (!$provided && isset($element['#localized_options']['menu_views'])) { $provided = &$element['#localized_options']['menu_views']; } // If the menu view element were not set, attempt to determine if this is a form. if (!$provided && isset($element['options'])) { if (isset($element['options']['#tree']) && $element['options']['#tree']) { $item['tree'] = TRUE; } if (isset($element['original_item']['#value']['options']['menu_views'])) { $provided = &$element['original_item']['#value']['options']['menu_views']; } if ($item['tree'] && isset($form_state['values']['options']['menu_views'])) { $provided = &$form_state['values']['options']['menu_views']; } elseif (isset($form_state['values']['menu_views'])) { $provided = &$form_state['values']['menu_views']; } if (isset($form_state['values']['menu_item_type'])) { $item['type'] = $form_state['values']['menu_item_type']; } } // By default, the menu view returns default values (no view). If settings were provided by an element or form item, then use those. if ($provided) { // Extract available element settings to use for this menu view. foreach (array('mlid', 'type', 'original_path', 'view') as $property) { if (isset($provided[$property]) && !empty($provided[$property])) { if (is_array($item[$property])) { $item[$property] = array_merge($item[$property], (array)$provided[$property]); } else { $item[$property] = $provided[$property]; } } } } // Filter out any disabled views. $views = array_keys(views_get_enabled_views()); if (!in_array($item['view']['name'], $views)) { $item['view'] = $default['view']; } return $item; } /** * Helper function to remove the attached view options from a menu item. */ function _menu_views_remove_element($item) { if ($item['element']) { unset($item['element']); } } /** * Helper function to tokenize an attached menu item view's arguments. */ function _menu_views_tokenize_arguments($item, $human_readable = FALSE) { $args = explode('/', $item['view']['arguments']); if (count($args) && $item['mlid']) { $context['menu-link'] = menu_link_load($item['mlid']); $options = array( 'callback' => '_menu_views_tokens_callback', 'clear' => TRUE, 'human_readable' => $human_readable, ); foreach ($args as $key => $arg) { $args[$key] = token_replace($arg, $context, $options); } } return implode('/', $args); } /** * Implements hook_token_info(). */ function menu_views_token_info() { $tokens['tokens']['menu-link']['node'] = array( 'name' => t('Node'), 'description' => t('The node of the menu link.'), 'type' => 'node', ); $tokens['tokens']['menu-link']['parent']['node'] = array( 'name' => t('Node'), 'description' => t('The node of the menu link\'s parent.'), 'type' => 'node', ); return $tokens; } /** * Implements hook_tokens(). */ function menu_views_tokens($type, $tokens, array $data = array(), array $options = array()) { $url_options = array('absolute' => TRUE); if (isset($options['language'])) { $url_options['language'] = $options['language']; $language_code = $options['language']->language; } else { $language_code = NULL; } $sanitize = !empty($options['sanitize']); $replacements = array(); $node = FALSE; $parent = FALSE; // Menu link tokens. if ($type == 'menu-link' && !empty($data['menu-link'])) { $link = (array) $data['menu-link']; foreach ($tokens as $name => $original) { switch ($name) { case 'node': $node = menu_get_object('node', 1, $link['link_path']); if ($node && $node->nid) { $title = $node->title; $replacements[$original] = $sanitize ? filter_xss($title) : $title; } else { $replacements[$original] = NULL; } break; case 'parent': if (isset($link['plid']) && !empty($link['plid']) && ($parent = menu_link_load($link['plid'])) && ($node = menu_get_object('node', 1, $parent['link_path'])) && $node->nid ) { $title = $node->title; $replacements[$original] = $sanitize ? filter_xss($title) : $title; } else { $replacements[$original] = NULL; } break; } } // Chained token relationships. if (($node_tokens = token_find_with_prefix($tokens, 'node')) && $node = menu_get_object('node', 1, $link['link_path']) ) { $replacements += token_generate('node', $node_tokens, array('node' => $node), $options); } if (($parent_tokens = token_find_with_prefix($tokens, 'parent')) && isset($link['plid']) && !empty($link['plid']) && ($parent = menu_link_load($link['plid'])) && ($node = menu_get_object('node', 1, $parent['link_path'])) && $node->nid ) { $replacements += token_generate('node', $parent_tokens, array('node' => $node), $options); } } return $replacements; } /** * Callback for human-readable token value replacements. */ function _menu_views_tokens_callback(&$replacements, $data, $options) { foreach ($replacements as $token => $value) { if ($options['human_readable']) { if (is_bool($value)) { $value = $value ? t('TRUE') : t('FALSE'); } elseif (is_object($value)) { $value = t('Object'); } elseif (is_array($value)) { $value = t('Array'); } elseif (is_null($value)) { $value = t('NULL'); } else { $value = (string) $value; } if ($value === '') { $value = t('NULL'); } } $replacements[$token] = urlencode($value); } }