You are here

advanced_menu_submenu.module in Advanced Menu 7

Provides advanced menu submenus.

File

submenu/advanced_menu_submenu.module
View source
<?php

// $Id: advanced_menu_submenu.module $

/**
 * @file
 * Provides advanced menu submenus.
 */

/**
 * Implementation of hook_permission().
 */
function advanced_menu_submenu_permission() {
  return array(
    'use sub menus' => array(
      'title' => t('Use Sub Menus'),
      'description' => t('Allow menus to be embedded within other menus.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function advanced_menu_submenu_menu() {
  $items['admin/structure/menu/manage/%menu/add-submenu'] = array(
    'title' => 'Add submenu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'menu_edit_item',
      'add',
      NULL,
      4,
    ),
    'access arguments' => array(
      'use sub menus',
    ),
    'type' => MENU_LOCAL_ACTION,
    'file' => 'menu.admin.inc',
    'file path' => drupal_get_path('module', 'menu'),
  );
  $items['advanced-menus/sub-menus/%menu'] = array(
    'title' => 'Sub Menus',
    'access callback' => TRUE,
    'page callback' => '_advanced_menu_submenu_callback',
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_form_alter().
 */
function advanced_menu_submenu_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
    case 'menu_edit_item':
      $url_comp = explode('/', request_path());
      $url_action = array_pop($url_comp);
      $url_menu = array_pop($url_comp);
      $default_value = NULL;
      if ($url_action == 'add-submenu' || substr($form['link_path']['#default_value'], 0, 24) == "advanced-menus/sub-menus") {
        if (substr($form['link_path']['#default_value'], 0, 24) == "advanced-menus/sub-menus") {
          $url_menu = $form['original_item']['#value']['menu_name'];
          $default_value = $form['link_path']['#default_value'];
        }
        $form['link_title'] = array(
          '#type' => 'hidden',
          '#value' => 'Sub-Menu',
          '#required' => FALSE,
        );
        $menus = _advanced_menu_submenu_menus($url_menu, $default_value);
        $options = array();
        foreach ($menus as $key => $value) {
          $options['advanced-menus/sub-menus/' . $key] = $value;
        }
        $form['link_path'] = array(
          '#type' => 'select',
          '#title' => t('Sub Menu'),
          '#options' => $options,
          '#description' => t('The menu to include as a sub menu.'),
          '#attributes' => array(
            'class' => array(
              'menu-title-select',
            ),
          ),
        );
        if (!empty($default_value)) {
          $form['link_path']['#default_value'] = $default_value;
        }
        $form['description'] = array(
          '#type' => 'hidden',
        );
        $form['expanded'] = array(
          '#type' => 'hidden',
          '#value' => 0,
        );
      }
      break;
  }
}

/**
 * Implements hook_block_view_alter().
 */
function advanced_menu_submenu_block_view_alter(&$data, $block) {
  global $user, $language;
  $system_menus = array(
    'navigation',
    'management',
    'user-menu',
    'main-menu',
  );
  if ($block->module == 'superfish') {
    list($menu_name, $mlid) = explode(':', variable_get('superfish_menu_' . $block->delta, 'main-menu:0'));
    $cache_key = 'links:' . $menu_name . ':all-cid:' . $mlid . ':' . $user->uid . ':' . $language->language;
    _advanced_menu_submenu_cache($cache_key);
    $data = superfish_contents($block->delta);
  }
  if (in_array($block->delta, $system_menus) && $block->module == 'system' || ($block->module == 'menu' || $block->module == 'menu_block')) {
    $new_content = array();
    $orig_content = $data['content'];
    if ($block->module == 'menu_block') {
      $orig_content = $data['content']['#content'];
    }
    foreach ($orig_content as $key => $item) {
      if (is_numeric($key)) {
        $new_data = _advanced_menu_submenu_trees($item);
        if ($new_data != $orig_content[$key]) {
          $orig_content[$key] = $new_data;
          if (is_array($new_data)) {
            $new_content = array_merge($new_content, $new_data);
          }
          else {
            $new_content[$key] = $new_data;
          }
        }
        else {
          $new_content[$key] = $item;
        }
      }
      else {
        $new_content[$key] = $item;
      }
    }
    if ($block->module == 'menu_block') {
      $data['content']['#content'] = $new_content;
    }
    else {
      $data['content'] = $new_content;
    }
  }
}

/**
 * Implements hook_menu_link_alter().
 */
function advanced_menu_submenu_menu_link_alter(&$item) {
  $original_path = explode('/', $item['link_path']);
  $alter_path = array_pop($original_path);
  $original_path = implode('/', $original_path);
  if ($original_path == 'advanced-menus/sub-menus') {
    $query = db_select('menu_custom', 'm')
      ->fields('m', array(
      'title',
    ))
      ->condition('menu_name', $alter_path)
      ->execute()
      ->fetchAssoc();
    $item['link_title'] = 'Submenu : ' . $query['title'];
  }
}

/**
 * Helper function to update menu cache for block display.
 */
function _advanced_menu_submenu_cache($cache_key) {
  $cache = cache_get($cache_key, 'cache_menu');
  if ($cache && isset($cache->data)) {

    //Update the menu cache if needed.
    foreach ($cache->data['menu'] as $key => $menu) {
      $cache->data['menu'][$key] = _advanced_menu_submenu_cache_recursive($menu);
    }
    cache_set($cache_key, $cache->data, 'cache_menu');
  }
  else {

    //Build the menu cache.
    $cache = array();
    $cache['menu'] = menu_tree_all_data($menu_name);
    foreach ($cache['menu'] as $key => $menu) {
      $cache['menu'][$key] = _advanced_menu_submenu_cache_recursive($menu);
    }
    cache_set($cache_key, $cache, 'cache_menu');
  }
}

/**
 * Recursive helper function for menu cache.
 */
function _advanced_menu_submenu_cache_recursive($menu_item) {
  $new_items = $menu_item;
  if (isset($menu_item['link']) && $menu_item['link']['router_path'] == 'advanced-menus/sub-menus/%') {
    $original_path = explode('/', $menu_item['link']['link_path']);
    $alter_path = array_pop($original_path);
    $original_path = implode('/', $original_path);
    $new_items = menu_tree_all_data($alter_path);
  }
  if (isset($new_items['below'])) {
    $below = array();
    foreach ($new_items['below'] as $key => $menu) {
      if (isset($menu['link']) && $menu['link']['router_path'] == 'advanced-menus/sub-menus/%') {
        $below = _advanced_menu_submenu_cache_recursive($menu);
      }
    }
    if (!empty($below)) {
      $new_items['below'] = $below;
    }
  }
  return $new_items;
}

/**
 * Helper function to build out sub-menus for block display.
 */
function _advanced_menu_submenu_trees($item) {
  $new_items = $item;
  $alter_path = '';
  if (is_array($new_items)) {
    if (isset($item['#original_link']) && $item['#original_link']['router_path'] == 'advanced-menus/sub-menus/%') {
      $original_path = explode('/', $item['#original_link']['link_path']);
      $alter_path = array_pop($original_path);
      $original_path = implode('/', $original_path);
      $new_items = menu_tree($alter_path);
      foreach ($new_items as $key => $new_item) {
        $new_items[$key] = _advanced_menu_submenu_trees($new_item);
      }
    }
    if (!empty($new_items['#below'])) {
      foreach ($new_items['#below'] as $key => $below) {
        $new_data = _advanced_menu_submenu_trees($below);
        if (is_array($new_data)) {
          if (isset($new_items['#below'][$key]['#original_link']) && $new_items['#below'][$key]['#original_link']['router_path'] == 'advanced-menus/sub-menus/%') {
            unset($new_items['#below'][$key]);
          }
          $new_items['#below'] = array_merge($new_items['#below'], $new_data);
        }
        else {
          $new_items['#below'][$key] = $new_data;
        }
        if (is_array($new_data) && _advanced_menu_submenu_is_active($new_data)) {
          $new_items['#attributes']['class'][] = 'active-trail';
          $new_items['#localized_options']['attributes']['class'][] = 'active-trail';
        }
      }
    }
  }
  return $new_items;
}

/**
 * Helper function to determine if the given items are in the active menu path.
 */
function _advanced_menu_submenu_is_active($new_item) {
  $is_active = FALSE;
  foreach ($new_item as $item) {
    if (is_array($item)) {
      if (isset($item['#original_link']) && $item['#original_link']['in_active_trail'] == 1) {
        $is_active = TRUE;
      }
    }
  }
  return $is_active;
}

/**
 * Helper function to determine what menus can be linked to from a given menu.
 */
function _advanced_menu_submenu_menus($menu, $default_value = NULL) {

  //Load available menus.
  if (module_exists('advanced_menu_menu_admin')) {
    $menus = _advanced_menu_menu_admin_menus();
  }
  else {
    $menus = menu_get_menus();
  }
  $exclude_menus = _advanced_menu_submenu_cycle($menu, $default_value);

  //Remove menus which would create a circular reference.
  foreach ($exclude_menus as $key => $value) {
    unset($menus[$value]);
  }
  if (empty($menus)) {
    drupal_set_message('No eligible sub menus were found.', 'warning');
  }
  return $menus;
}

/**
 * Recursive Helper function to cycle through the menus and determine what links where.
 */
function _advanced_menu_submenu_cycle($menu, $default_value = NULL) {
  $menus = array();
  $menus[$menu] = $menu;
  $query = db_select('menu_links', 'm')
    ->fields('m', array(
    'menu_name',
  ))
    ->condition('link_path', 'advanced-menus/sub-menus/' . $menu, '=')
    ->execute();
  if ($query) {
    while ($record = $query
      ->fetchAssoc()) {
      $p_menus = _advanced_menu_submenu_cycle($record['menu_name']);
      $menus = array_merge($menus, $p_menus);
    }
  }
  if (!empty($default_value)) {
    $query = db_select('menu_links', 'm')
      ->fields('m', array(
      'link_path',
    ))
      ->condition('link_path', 'advanced-menus/sub-menus/%', 'LIKE')
      ->condition('link_path', $default_value, '!=')
      ->condition('menu_name', $menu, '=')
      ->execute();
    if ($query) {
      while ($record = $query
        ->fetchAssoc()) {
        $p_path = explode('/', $record['link_path']);
        $p_menu = array_pop($p_path);
        $p_menus = array(
          $p_menu,
        );
        $menus = array_merge($menus, $p_menus);
      }
    }
  }
  return $menus;
}
function _advanced_menu_submenu_callback() {
  drupal_goto('<front>');
}

Functions

Namesort descending Description
advanced_menu_submenu_block_view_alter Implements hook_block_view_alter().
advanced_menu_submenu_form_alter Implementation of hook_form_alter().
advanced_menu_submenu_menu Implements hook_menu().
advanced_menu_submenu_menu_link_alter Implements hook_menu_link_alter().
advanced_menu_submenu_permission Implementation of hook_permission().
_advanced_menu_submenu_cache Helper function to update menu cache for block display.
_advanced_menu_submenu_cache_recursive Recursive helper function for menu cache.
_advanced_menu_submenu_callback
_advanced_menu_submenu_cycle Recursive Helper function to cycle through the menus and determine what links where.
_advanced_menu_submenu_is_active Helper function to determine if the given items are in the active menu path.
_advanced_menu_submenu_menus Helper function to determine what menus can be linked to from a given menu.
_advanced_menu_submenu_trees Helper function to build out sub-menus for block display.