You are here

menu_views.module in Menu Views 8.3

Same filename and directory in other branches
  1. 7.2 menu_views.module
  2. 7 menu_views.module

Module to allow Views to be attached as menu items.

This module is a utility module and allows an admin to select a view for a menu item instead of a title and link. When the link is rendered, the view is inserted instead of the link. In addition, if the parent item of the menu is a node page, the node id can be passed to the view as an argument using tokens.

Original concept by Randall Knutson - LevelTen Interactive. Written and maintained by Mark Carver - LevelTen Interactive. http://www.leveltendesign.com

File

menu_views.module
View source
<?php

/**
 * @file
 * Module to allow Views to be attached as menu items.
 *
 * This module is a utility module and allows an admin to select a view for a menu item instead of a title and link. When
 * the link is rendered, the view is inserted instead of the link. In addition, if the
 * parent item of the menu is a node page, the node id can be passed to the view as an argument using tokens.
 *
 * Original concept by Randall Knutson - LevelTen Interactive.
 * Written and maintained by Mark Carver - LevelTen Interactive.
 * http://www.leveltendesign.com
 */

// Include admin form alter hooks.
include_once 'menu_views.admin.inc';

/**
 * Implements hook_menu().
 */
function menu_views_menu() {

  // Fake callback, needed for menu item add/edit validation.
  $items['<view>'] = 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';
  }

  // Provide Responsive Dropdown Menus support.
  if (isset($registry['responsive_dropdown_menus_item_link'])) {
    $registry['menu_views_responsive_dropdown_menus_item_link_default'] = $registry['responsive_dropdown_menus_item_link'];
    $registry['responsive_dropdown_menus_item_link']['function'] = 'menu_views_responsive_dropdown_menus_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.
  $view = _menu_views_replace_menu_item($variables['element']);
  if ($view !== FALSE) {
    if (!empty($view)) {
      $sub_menu = '';
      $classes = isset($variables['element']['#attributes']['class']) ? $variables['element']['#attributes']['class'] : array();
      $item = _menu_views_get_item($variables['element']);
      foreach (explode(' ', $item['view']['settings']['wrapper_classes']) as $class) {
        if (!in_array($class, $classes)) {
          $classes[] = $class;
        }
      }
      $variables['element']['#attributes']['class'] = $classes;
      if ($variables['element']['#below']) {
        $sub_menu = drupal_render($variables['element']['#below']);
      }
      return '<li' . drupal_attributes($variables['element']['#attributes']) . '>' . $view . $sub_menu . "</li>\n";
    }
    return '';
  }

  // 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) {
  if (isset($variables['menu_item']['link'])) {

    // Only intercept if this menu item link is a view.
    if ($view = _menu_views_replace_menu_item($variables['menu_item']['link'])) {
      $item = _menu_views_get_item($variables['menu_item']['link']);
      return '<div' . drupal_attributes(array(
        'class' => explode(' ', $item['view']['settings']['wrapper_classes']),
      )) . '>' . $view . '</div>';
    }
    elseif ($variables['menu_item']['link']['link_path'] == '<view>') {
      return '';
    }
  }

  // Otherwise, use the default theming function.
  return theme('menu_views_superfish_menu_item_link_default', $variables);
}

/**
 * Implements theme_responsive_dropdown_menus_item_link().
 * Overrides default theming function to intercept views.
 */
function menu_views_responsive_dropdown_menus_item_link(array $variables) {
  if (isset($variables['menu_item']['link'])) {

    // Only intercept if this menu item link is a view.
    if ($view = _menu_views_replace_menu_item($variables['menu_item']['link'])) {
      $item = _menu_views_get_item($variables['menu_item']['link']);
      return '<div' . drupal_attributes(array(
        'class' => explode(' ', $item['view']['settings']['wrapper_classes']),
      )) . '>' . $view . '</div>';
    }
    elseif ($variables['menu_item']['link']['link_path'] == '<view>') {
      return '';
    }
  }

  // Otherwise, use the default theming function.
  return theme('menu_views_responsive_dropdown_menus_item_link_default', $variables);
}

/**
 * Implements hook_menu_breadcrumb_alter().
 */
function menu_views_menu_breadcrumb_alter(&$active_trail, $item) {
  foreach ($active_trail as $key => $parent) {
    if (isset($parent['link_path']) && $parent['link_path'] == '<view>') {
      $menu_view = _menu_views_get_item($parent);
      _menu_views_tokenize($menu_view);

      // Remove this breadcrumb if the menu item view wants it hidden.
      if (!(bool) $menu_view['view']['settings']['breadcrumb']) {
        unset($active_trail[$key]);
      }
      else {

        // Use overridden title if provided.
        $title = filter_xss_admin($menu_view['view']['settings']['breadcrumb_title']);

        // Use title provided by view next.
        if (empty($title)) {
          $view = views_get_view($menu_view['view']['name']);
          if ($view && $view
            ->access($menu_view['view']['display']) && $view
            ->set_display($menu_view['view']['display'])) {
            $title = filter_xss_admin($view
              ->get_title());
            $view
              ->destroy();
          }
        }

        // If title is still empty, just remove it from the breadcrumb.
        if (empty($title)) {
          unset($active_trail[$key]);
        }
        else {
          $active_trail[$key]['title'] = $title;
          $active_trail[$key]['href'] = $menu_view['view']['settings']['breadcrumb_path'];
        }
      }
    }
  }
}
function _menu_views_replace_menu_item($element) {
  $build = array();
  $item = _menu_views_get_item($element);
  _menu_views_tokenize($item);
  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'])) {
        $arguments = explode('/', $item['view']['arguments']);

        // Need to replace empty arguments with NULL values for views.
        foreach ($arguments as $key => $value) {
          if (empty($value)) {
            $arguments[$key] = NULL;
          }
        }
        $view
          ->set_arguments($arguments);
        $build['view'] = array(
          '#markup' => $view
            ->preview(),
          '#weight' => 10,
        );

        // Provide title options for the view.
        if ((bool) $item['view']['settings']['title']) {
          $title = filter_xss_admin($item['view']['settings']['title_override']);
          if (empty($title)) {
            $title = filter_xss_admin($view
              ->get_title());
          }
          if (!empty($title)) {
            $tag = $item['view']['settings']['title_wrapper'];
            if ($tag === '0') {
              $tag = FALSE;
            }
            elseif ($tag === '') {
              $tag = 'h3';
            }
            if ($tag) {
              $title_attributes = array();
              if (!empty($item['view']['settings']['title_classes'])) {
                $title_attributes['class'] = array_filter(explode(' ', $item['view']['settings']['title_classes']));
                foreach ($title_attributes['class'] as $key => $class) {
                  $title_attributes['class'][$key] = drupal_html_class($class);
                }
              }
              $build['title'] = array(
                '#theme' => 'html_tag__menu_views__title',
                '#tag' => $tag,
                '#attributes' => $title_attributes,
                '#value' => filter_xss_admin($title),
              );
            }
            else {
              $build['title'] = array(
                '#markup' => $title,
              );
            }
          }
        }

        // Add contextual links if allowed and if views_ui module is enabled.
        if (module_exists('contextual_links') && user_access('access contextual links') && module_exists('views_ui')) {
          views_add_contextual_links($build, 'special_block_-exp', $view, $item['view']['display']);
          if (!empty($build['#contextual_links'])) {
            $build['#prefix'] = '<div class="contextual-links-region">';
            $build['#suffix'] = '</div>';
            $build['contextual_links'] = array(
              '#type' => 'contextual_links',
              '#contextual_links' => $build['#contextual_links'],
              '#element' => $build,
              '#weight' => -1,
            );
          }
        }
        $view
          ->destroy();
      }
    }
    return drupal_render($build);
  }
  return FALSE;
}
function _menu_views_default_values() {
  return array(
    'mlid' => 0,
    'type' => 'link',
    'original_path' => '',
    'view' => array(
      'name' => FALSE,
      'display' => FALSE,
      'arguments' => '',
      'settings' => array(
        'wrapper_classes' => 'menu-views',
        'breadcrumb' => TRUE,
        'breadcrumb_title' => '',
        'breadcrumb_path' => '<front>',
        'title' => FALSE,
        'title_wrapper' => '',
        'title_classes' => '',
        'title_override' => '',
      ),
    ),
  );
}

/**
 * Helper function to determine whether the form menu item options are a tree.
 */
function _menu_views_options_tree($form) {
  return isset($form['#node']) && isset($form['menu']['link']['options']['#tree']) && $form['menu']['link']['options']['#tree'] || isset($form['options']['#tree']) && $form['options']['#tree'];
}

/**
 * Helper function to return the menu view array from a menu item array or form array.
 */
function _menu_views_get_item(array &$element = array(), array &$form_state = array()) {

  // Default values.
  $item = $default = _menu_views_default_values();

  // Remove the type of menu item, will get set afterwards.
  unset($item['type']);
  $provided = FALSE;
  $ajax_type = FALSE;

  // If $form_state is empty, this is a menu item.
  if (empty($form_state)) {
    if (isset($element['menu_views'])) {
      $provided =& $element['menu_views'];
    }
    elseif (isset($element['localized_options']['menu_views'])) {
      $provided =& $element['localized_options']['menu_views'];
    }
    elseif (isset($element['#localized_options']['menu_views'])) {
      $provided =& $element['#localized_options']['menu_views'];
    }
    elseif (isset($element['options']['menu_views'])) {
      $provided =& $element['options']['menu_views'];
    }
  }
  else {
    $original_element = $element;
    $values =& $form_state['values'];

    // Determine if this is a node form.
    if (isset($element['#node'])) {
      $element =& $element['menu']['link'];
      $values =& $values['menu'];
    }

    // Save the menu item type before proceeding.
    if (isset($values['menu_item_type'])) {
      $ajax_type = $values['menu_item_type'];
    }
    elseif (isset($values['menu']['menu_views']['menu_item_type'])) {
      $ajax_type = $values['menu']['menu_views']['menu_item_type'];
    }

    // Save the menu item provided for initial form population.
    if (isset($element['original_item']['#value']['options']['menu_views'])) {
      $provided =& $element['original_item']['#value']['options']['menu_views'];
      if (isset($provided['type'])) {
        $item['type'] = $provided['type'];
      }
    }
    elseif (isset($original_element['#node']->menu['options']['menu_views'])) {
      $provided =& $original_element['#node']->menu['options']['menu_views'];
      if (isset($provided['type'])) {
        $item['type'] = $provided['type'];
      }
    }

    // Determine if the options has a tree value.
    if (_menu_views_options_tree($original_element)) {
      $element =& $element['options'];
      $values =& $values['options'];
    }
    if (!$provided && isset($element['menu_views'])) {
      if (isset($element['menu_views']['#value'])) {
        $provided = $element['menu_views']['#value'];
      }
      elseif (isset($element['menu_views'])) {
        $provided = $element['menu_views'];
      }
    }

    // Allow submitted values to override form values.
    if (isset($values['menu_views'])) {
      $provided = $values['menu_views'];
    }
    if (isset($provided['type']) && isset($item['type'])) {
      $provided['type'] = $item['type'];
    }
  }

  // If the menu view element were not set, attempt to determine if this is a form.
  // 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',
      'original_path',
      'view',
    ) as $property) {
      if (isset($provided[$property])) {
        if (isset($item[$property]) && is_array($item[$property])) {
          $item[$property] = _menu_views_array_merge_recursive($item[$property], $provided[$property]);
        }
        else {
          $item[$property] = $provided[$property];
        }
      }
    }
  }

  // Set the type of menu item.
  if ($ajax_type) {
    $item['type'] = $ajax_type;
  }
  elseif (isset($provided['type'])) {
    $item['type'] = $provided['type'];
  }
  else {
    $item['type'] = $default['type'];
  }

  // 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;
}
function menu_views_menu_link_alter(&$link) {
  $item = _menu_views_get_item($link);
  if ($item['type'] == 'view') {
    if (isset($link['link_path']) && $link['link_path'] != '<view>') {
      $item['original_path'] = $link['link_path'];
    }
    $link['link_path'] = '<view>';
    $link['options']['alter'] = TRUE;
  }
}

/**
 * Helper function to return the menu link item based on it's original path.
 *
 * @param (string) $original_path
 *   The [node] path for which to search for in menu views.
 * @param (string)|(array) $menu_name
 *   Limit the search of menu view items to the specified menu names.
 * @return
 *   (array) $mlids
 *   A keyed array containing the identification integers matching the original path of menu items in the {menu_links} table,
 *   or an empty array if no menu items were found.
 *
 * @see: menu_views_node_prepare() and menu_views_node_delete().
 */
function _menu_views_items_from_original_path($original_path, $menu_name = NULL) {
  $mlids = array();

  // Build the query.
  $query = db_select('menu_links', 'm')
    ->fields('m', array(
    'mlid',
    'options',
  ))
    ->condition('module', 'menu')
    ->condition('link_path', '<view>');

  // Set the menu_name condition if present.
  if (!empty($menu_name)) {
    $query = $query
      ->condition('menu_name', $menu_name);
  }

  // Execute the query.
  $query = $query
    ->execute();

  // Iterate through all available menu items that are views to match against the original path.
  while ($link = $query
    ->fetchObject()) {
    if ($options = unserialize($link->options)) {
      $item = _menu_views_get_item($options);
      if ($item['original_path'] == $original_path) {
        $mlids[] = $link->mlid;
        break;
      }
    }
  }
  return $mlids;
}

/**
 * Implements hook_node_prepare().
 */
function menu_views_node_prepare($node) {

  // Manually call menu's hook_node_prepare() if $node->menu doesn't exist.
  // @see: drupal.org/node/1878968
  if (!isset($node->menu) || empty($node->menu)) {
    menu_node_prepare($node);
  }
  if (isset($node->nid) && !$node->menu['mlid']) {

    // Prepare the node for the edit form so that $node->menu always exists.
    $menu_name = strtok(variable_get('menu_parent_' . $node->type, 'main-menu:0'), ':');
    $item = array();
    $mlids = array();

    // Give priority to the default menu.
    $type_menus = variable_get('menu_options_' . $node->type, array(
      'main-menu' => 'main-menu',
    ));
    if (in_array($menu_name, $type_menus)) {
      $mlids = _menu_views_items_from_original_path('node/' . $node->nid, $menu_name);
    }

    // Check all allowed menus if a link does not exist in the default menu.
    if (empty($mlid) && !empty($type_menus)) {
      $mlids = _menu_views_items_from_original_path('node/' . $node->nid, array_values($type_menus));
    }

    // Load the menu link if one was found.
    $item = empty($mlids) ? array() : menu_link_load(reset($mlids));

    // Set default values.
    $default = array(
      'link_title' => '',
      'mlid' => 0,
      'plid' => 0,
      'menu_name' => $menu_name,
      'weight' => 0,
      'options' => array(),
      'module' => 'menu',
      'expanded' => 0,
      'hidden' => 0,
      'has_children' => 0,
      'customized' => 0,
    );

    // Set the menu item.
    $node->menu = _menu_views_array_merge_recursive($default, $item);

    // Find the depth limit for the parent select.
    if (!isset($node->menu['parent_depth_limit'])) {
      $node->menu['parent_depth_limit'] = _menu_parent_depth_limit($node->menu);
    }
  }
}

/**
 * Implements hook_node_delete().
 */
function menu_views_node_delete($node) {
  $mlids = _menu_views_items_from_original_path('node/' . $node->nid);
  foreach ($mlids as $mlid) {
    menu_link_delete($mlid);
  }
}

/**
 * Implements hook_node_insert().
 */
function menu_views_node_insert($node) {
  menu_views_node_save($node);
}

/**
 * Implements hook_node_presave().
 */
function menu_views_node_presave($node) {
  if (isset($node->menu)) {
    $link =& $node->menu;
    $item = _menu_views_get_item($link);

    // Ensure the enabled property is set.
    if (!isset($link['enabled'])) {
      $link['enabled'] = !(bool) $link['hidden'];
    }

    // If this is a menu view item, override properties on the link so this module handles the save.
    if ($link['enabled'] && $item['type'] == 'view') {

      // Save the mlid in the menu_views array so the menu module doesn't delete the link when it detects the mlid.
      if (!empty($link['mlid'])) {
        $link['options']['menu_views']['mlid'] = $link['mlid'];
        $link['mlid'] = 0;
      }

      // Ensure there is no title so the menu module doesn't try to save this menu item.
      $link['link_title'] = '';
    }
  }
}

/**
 * Implements hook_node_update().
 */
function menu_views_node_update($node) {
  menu_views_node_save($node);
}

/**
 * Helper for hook_node_insert() and hook_node_update().
 */
function menu_views_node_save($node) {
  if (isset($node->menu)) {
    $link =& $node->menu;
    $item = _menu_views_get_item($link);

    // Check to see if Menu Views should handle the menu item save.
    if (!empty($link['enabled']) && $item['type'] == 'view') {

      // If this an existing menu item, check to see if the mlid was saved in the menu view options array.
      if (!empty($item['mlid']) && empty($link['mlid'])) {
        $link['mlid'] = $item['mlid'];
      }
      elseif (empty($link['mlid'])) {
        if (!menu_link_save($link)) {
          drupal_set_message(t('There was an error saving the menu link.'), 'error');
          return;
        }
      }

      // Ensure mlid is properly set.
      $item['mlid'] = $link['mlid'];

      // Ensure link_path is properly set.
      $link['link_path'] = '<view>';

      // Ensure original_path is properly set.
      $item['original_path'] = 'node/' . $node->nid;

      // Replace the menu view options in the link and save it.
      $link['options']['menu_views'] = $item;
      if (!menu_link_save($link)) {
        drupal_set_message(t('There was an error saving the menu link.'), 'error');
      }
    }
  }
}

/**
 * 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();

  // Menu link tokens.
  if ($type == 'menu-link' && !empty($data['menu-link'])) {
    $link = (array) $data['menu-link'];

    // menu-link:node tokens.
    if ($node_tokens = token_find_with_prefix($tokens, 'node')) {
      $node = menu_get_object('node', 1, $link['link_path']);
      if (!$node && '<view>' === $link['link_path'] && !empty($link['options']['menu_views']['original_path'])) {
        $node = menu_get_object('node', 1, $link['options']['menu_views']['original_path']);
      }
      if ($node) {
        $replacements += token_generate('node', $node_tokens, array(
          'node' => $node,
        ), $options);
      }
      else {
        $replacements += token_generate('node', $node_tokens, array(
          'node' => NULL,
        ), $options);
      }
    }
    elseif (($parent_tokens = token_find_with_prefix($tokens, 'parent')) && !empty($link['plid']) && ($parent = menu_link_load($link['plid']))) {
      $node = menu_get_object('node', 1, $parent['link_path']);
      if (!$node && '<view>' === $parent['link_path'] && !empty($parent['options']['menu_views']['original_path'])) {
        $node = menu_get_object('node', 1, $parent['options']['menu_views']['original_path']);
      }
      if ($node) {
        $replacements += token_generate('node', $parent_tokens, array(
          'node' => $node,
        ), $options);
      }
      else {
        $replacements += token_generate('node', $parent_tokens, array(
          'node' => NULL,
        ), $options);
      }
    }
  }
  return $replacements;
}

/**
 * Helper function to tokenize a menu item view arguments and settings.
 * Alters the menu view item array and the original values are replaced.
 */
function _menu_views_tokenize(&$item) {
  if (isset($item['mlid']) && $item['mlid'] > 0) {
    $context['menu-link'] = menu_link_load($item['mlid']);
    $options = array(
      'callback' => '_menu_views_tokenize_callback',
    );
    if (isset($item['view']['arguments']) && !empty($item['view']['arguments'])) {
      $item['view']['arguments'] = token_replace($item['view']['arguments'], $context, array_merge($options, array(
        'urlencode' => TRUE,
        'clear' => TRUE,
      )));
    }
    $tokenizable_settings = array(
      'breadcrumb_title',
      'breadcrumb_path',
      'title_override',
    );
    if (isset($item['view']['settings'])) {
      foreach ($item['view']['settings'] as $key => $value) {
        if (in_array($key, $tokenizable_settings)) {
          $item['view']['settings'][$key] = token_replace($value, $context, $options);
        }
      }
    }
  }
}

/**
 * Callback for human-readable token value replacements.
 */
function _menu_views_tokenize_callback(&$replacements, $data, $options) {
  foreach ($replacements as $token => $value) {
    if (isset($options['urlencode']) && $options['urlencode']) {
      $replacements[$token] = urlencode($value);
    }
  }
}

/**
 * array_merge_recursive does indeed merge arrays, but it converts values with duplicate
 * keys to arrays rather than overwriting the value in the first array with the duplicate
 * value in the second array, as array_merge does. I.e., with array_merge_recursive,
 * this happens (documented behavior):
 *
 * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
 *     => array('key' => array('org value', 'new value'));
 *
 * array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
 * Matching keys' values in the second array overwrite those in the first array, as is the
 * case with array_merge, i.e.:
 *
 * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
 *     => array('key' => 'new value');
 *
 * Parameters are passed by reference, though only for performance reasons. They're not
 * altered by this function.
 *
 * @param array $array1
 * @param mixed $array2
 * @author daniel@danielsmedegaardbuus.dk
 * @return array
 */
function &_menu_views_array_merge_recursive(array &$array1, &$array2 = NULL) {
  $merged = $array1;
  if (is_array($array2)) {
    foreach ($array2 as $key => $val) {
      if (is_array($array2[$key])) {
        $merged[$key] = isset($merged[$key]) && is_array($merged[$key]) ? _menu_views_array_merge_recursive($merged[$key], $array2[$key]) : $array2[$key];
      }
      else {
        $merged[$key] = $val;
      }
    }
  }
  return $merged;
}

Functions

Namesort descending Description
menu_views_menu Implements hook_menu().
menu_views_menu_breadcrumb_alter Implements hook_menu_breadcrumb_alter().
menu_views_menu_link Implements theme_menu_link(). Overrides default theming function to intercept views.
menu_views_menu_link_alter
menu_views_node_delete Implements hook_node_delete().
menu_views_node_insert Implements hook_node_insert().
menu_views_node_prepare Implements hook_node_prepare().
menu_views_node_presave Implements hook_node_presave().
menu_views_node_save Helper for hook_node_insert() and hook_node_update().
menu_views_node_update Implements hook_node_update().
menu_views_permission Implements hook_permission().
menu_views_responsive_dropdown_menus_item_link Implements theme_responsive_dropdown_menus_item_link(). Overrides default theming function to intercept views.
menu_views_superfish_menu_item_link Implements theme_superfish_menu_item_link(). Overrides default theming function to intercept views.
menu_views_theme_registry_alter Implements hook_theme_registry_alter(). Intercepts theme_menu_link().
menu_views_tokens Implements hook_tokens().
menu_views_token_info Implements hook_token_info().
_menu_views_array_merge_recursive array_merge_recursive does indeed merge arrays, but it converts values with duplicate keys to arrays rather than overwriting the value in the first array with the duplicate value in the second array, as array_merge does. I.e., with…
_menu_views_default_values
_menu_views_get_item Helper function to return the menu view array from a menu item array or form array.
_menu_views_items_from_original_path Helper function to return the menu link item based on it's original path.
_menu_views_options_tree Helper function to determine whether the form menu item options are a tree.
_menu_views_replace_menu_item
_menu_views_tokenize Helper function to tokenize a menu item view arguments and settings. Alters the menu view item array and the original values are replaced.
_menu_views_tokenize_callback Callback for human-readable token value replacements.