You are here

menu_block_split.module in Menu Block Split 7.2

Allow a menu to be split over two blocks Developed by Robert Garrigos <robert@garrigos.cat> Modified for Drupal 6.x by Frank Meyerer <meyerer@digi-info.de> http://www.digi-info.de currently maintained by Bob Hutchinson http://drupal.org/user/52366

File

menu_block_split.module
View source
<?php

/**
 * @file
 * Allow a menu to be split over two blocks
 * Developed by Robert Garrigos <robert@garrigos.cat>
 * Modified for Drupal 6.x by Frank Meyerer <meyerer@digi-info.de>
 * http://www.digi-info.de
 * currently maintained by Bob Hutchinson http://drupal.org/user/52366
 */

/**
 * Since Drupal 6, the breadcrumbs only work for menu items in the 'Navigation' menu
 * The following two function 'fix' this issue to have correct breadcrumbs for ALL menu's
 * See http://drupal.org/node/184955 for more info on this fix.
 *
 * Roel De Meester - http://krimson.be
 * Updated for D7 by hutch http://drupal.org/user/52366
 */

/**
 * Implements hook_init().
 */
function menu_block_split_init() {
  $menu_names = menu_block_split_menu_name();
  if ($menu_names) {
    menu_set_active_menu_names($menu_names);
  }
}

/**
 * Returns the menu_name to which the current menu-item belongs.
 */
function menu_block_split_menu_name() {
  $item = menu_get_item();
  $query = db_select('menu_links', 'ml');
  $query
    ->fields('ml', array(
    'menu_name',
  ));
  $query
    ->condition('ml.link_path', $item['href']);
  $rows = $query
    ->execute()
    ->fetchAll();
  $rows_to_add = array();
  foreach ($rows as $row) {
    if (is_object($row)) {
      if (!in_array($row->menu_name, array(
        'navigation',
        'admin_menu',
      ))) {
        $rows_to_add[] = $row->menu_name;
      }
    }
  }
  return $rows_to_add;
}

/**
 * Implements hook_permission().
 */
function menu_block_split_permission() {
  return array(
    'administer menu block split' => array(
      'title' => t('Administer Menu Block Split'),
      'description' => t('Access the Menu Block Split administration page.'),
    ),
  );
}

/**
 * Implements hook_help().
 */
function menu_block_split_help($page, $arg) {
  switch ($page) {
    case 'admin/help#menu_block_split':
      $output = '';
      $output .= '<p>' . t('Menu Block Split allows any menu block to be split into two blocks: one with the first level menu entries and a second one for all the sublevels.') . '</p>';
      $output .= '<p>' . t('Once you set how many first level menu blocks you need you can go to the <a href="@blocks">blocks admin page</a> to admin your new blocks. You should find a new Menu Block Split second level block and as many Menu Block Split first level blocks as you have set.', array(
        '@blocks' => url('admin/build/block'),
      )) . '</p>';
      return $output;
  }
}

/**
 * Implements hook_menu().
 */
function menu_block_split_menu() {
  $items = array();
  $items['admin/config/user-interface/menu_block_split'] = array(
    'title' => 'Menu block split settings',
    'description' => 'Settings for Menu Block Split',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'menu_block_split_settings',
    ),
    'access arguments' => array(
      'administer menu block split',
    ),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Settings form.
 */
function menu_block_split_settings() {
  $level_options = range(0, 10);
  unset($level_options[0]);
  $form['menu_block_split_howmany'] = array(
    '#type' => 'select',
    '#title' => t('How many blocks with first level menu do you need?'),
    '#default_value' => variable_get('menu_block_split_howmany', 1),
    '#options' => $level_options,
    '#description' => t('Select how many first menu level blocks you need and click on the Save Configuration button to make the form available.'),
  );
  $menu_select_options = array();
  foreach (menu_get_menus() as $name => $title) {
    if (count(menu_navigation_links($name)) > 0) {
      $menu_select_options[$name] = $title;
    }
  }
  for ($i = 1; $i <= variable_get('menu_block_split_howmany', 1); $i++) {
    $form['menu_block_split_fieldset_' . $i] = array(
      '#type' => 'fieldset',
      '#title' => t('Menu Block Split !i', array(
        '!i' => $i,
      )),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    $form['menu_block_split_fieldset_' . $i]['menu_block_split_' . $i] = array(
      '#type' => 'select',
      '#title' => t('Block!i', array(
        '!i' => $i,
      )),
      '#options' => $menu_select_options,
      '#default_value' => variable_get('menu_block_split_' . $i, ''),
      '#description' => t('Choose a block as first level menu to split.'),
    );
    $default = check_plain(variable_get('menu_block_splittitle_' . $i, ''));
    $form['menu_block_split_fieldset_' . $i]['menu_block_splittitle_' . $i] = array(
      '#type' => 'textfield',
      '#title' => t('Title !i', array(
        '!i' => $i,
      )),
      '#default_value' => $default,
      '#required' => FALSE,
      '#description' => t('Set the title of the resulting block.'),
    );
  }
  $form['#validate'][] = 'menu_block_split_settings_validate';
  return system_settings_form($form);
}

/**
 * Settings form validate.
 */
function menu_block_split_settings_validate($form, &$form_state) {
  $howmany = $form_state['values']['menu_block_split_howmany'];
  for ($i = 1; $i <= $howmany; $i++) {
    $form_state['values']['menu_block_splittitle_' . $i] = check_plain($form_state['values']['menu_block_splittitle_' . $i]);
  }
}

/**
 * Implements hook_block_info().
 *
 * This hook declares what blocks are provided by the module.
 */
function menu_block_split_block_info() {
  $howmany = variable_get('menu_block_split_howmany', 1);
  for ($i = 1; $i <= $howmany; $i++) {
    $mid = variable_get('menu_block_split_' . $i, '');
    $item = menu_load($mid);
    $blocks[$i]['info'] = 'Menu block split 1st level (' . $item['title'] . ')';
  }
  $blocks[0]['info'] = 'Menu block split 2nd level';
  return $blocks;
}

/**
 * Implements hook_block_view().
 *
 * This hook generates the contents of the blocks themselves.
 */
function menu_block_split_block_view($delta = '') {
  $howmany = variable_get('menu_block_split_howmany', 1);
  $block = '';

  // Delta 0 is the 2nd level block
  if ($delta > 0) {
    $tree = menu_tree_page_data(variable_get('menu_block_split_' . $delta, ''));
    $block['subject'] = check_plain(variable_get('menu_block_splittitle_' . $delta, ''));
    $block['content'] = theme('menu_block_split_menu', array(
      'link' => variable_get('menu_block_split_' . $delta, ''),
      'tree' => $tree,
      'level' => $delta,
    ));
  }
  else {
    $current_router_item = menu_get_item();
    for ($i = 1; $i <= $howmany; $i++) {
      $name = variable_get('menu_block_split_' . $i, '');

      // now returns an array
      $active_arr = menu_get_active_menu_names();
      foreach ($active_arr as $active) {
        if ($active == $name) {
          $trail = menu_get_active_trail();
          $tree = menu_tree_page_data($name);
          $info = menu_block_split_get_first_level($trail);
          $block['subject'] = $info['title'];
          $block['content'] = theme('menu_block_split_menu', array(
            'link' => $name,
            'tree' => $tree,
            'level' => $delta,
          ));
          return $block;
        }
      }
    }
  }
  return $block;
}

/**
 * Render menu
 *
 * @param array $tree
 * @param int $level
 *
 * @return menu tree
 */
function menu_block_split_render_tree($tree, $level) {
  $output = '';
  $num_items = menu_block_split_count_active_items($tree);
  $n = 1;
  foreach ($tree as $i => $mid) {
    if ($mid['link']['hidden'] == 0) {
      $link = theme('menu_block_split_menu_item_link', array(
        'link' => $mid['link'],
      ));

      // our first block
      if ($level > 0) {
        $extra_class = 'menu-' . $mid['link']['mlid'];
        if ($n == 1) {
          $extra_class .= ' first ';
        }
        if ($n == $num_items) {
          $extra_class .= ' last ';
        }
        $trail = menu_get_active_trail();
        foreach ($trail as $item) {
          if (isset($item['mlid']) && $item['mlid'] == $mid['link']['mlid'] && $item['in_active_trail']) {
            $extra_class .= ' active-trail ';
          }
        }
        $output .= theme('menu_block_split_menu_item', array(
          'link' => $link,
          'has_children' => 0,
          'menu' => '',
          'in_active_trail' => isset($mid['link']['in_active_trail']) && $mid['link']['in_active_trail'],
          'extra_class' => $extra_class,
        ));
      }
      else {
        if ($mid['below']) {
          $output .= menu_block_split_menu_tree_output($mid['below']);
        }
      }
    }
    $n++;
  }
  return $output;
}

/**
 * Count the number of active items in a menu.
 *
 * @param array $tree
 * @return int
 */
function menu_block_split_count_active_items($tree) {
  $count = 0;
  foreach ($tree as $item) {
    if ($item['link']['hidden'] == 0) {
      $count++;
    }
  }
  return $count;
}

/**
 * Get info about first level.
 *
 * @param array $trail current trail
 *
 * @return title
 */
function menu_block_split_get_first_level($trail) {
  $info = array(
    'mlid' => isset($trail[1]['mlid']) ? $trail[1]['mlid'] : NULL,
    'title' => isset($trail[1]['title']) ? $trail[1]['title'] : '',
  );
  return $info;
}

/**
 * outputs a menu tree.
 *
 * @param array $tree
 *
 * @return
 *   Themed menu tree.
 */
function menu_block_split_menu_tree_output($tree) {
  $output = '';
  $items = array();

  // Pull out just the menu items we are going to render so that we
  // get an accurate count for the first/last classes.
  foreach ($tree as $data) {
    if (!$data['link']['hidden']) {
      $items[] = $data;
    }
  }
  $num_items = count($items);
  foreach ($items as $i => $data) {
    $extra_class = NULL;
    if ($i == 0) {
      $extra_class = 'first menu-' . $data['link']['mlid'];
    }
    if ($i == $num_items - 1) {
      $extra_class = 'last menu-' . $data['link']['mlid'];
    }
    $link = theme('menu_block_split_menu_item_link', array(
      'link' => $data['link'],
    ));
    if ($data['below']) {
      $output .= theme('menu_block_split_menu_item', array(
        'link' => $link,
        'has_children' => $data['link']['has_children'],
        'menu' => menu_tree_output($data['below']),
        'in_active_trail' => $data['link']['in_active_trail'],
        'extra_class' => $extra_class,
      ));
    }
    else {
      $output .= theme('menu_block_split_menu_item', array(
        'link' => $link,
        'has_children' => $data['link']['has_children'],
        'menu' => '',
        'in_active_trail' => $data['link']['in_active_trail'],
        'extra_class' => $extra_class,
      ));
    }
  }
  return $output;
}

/**
 * Implementation of hook_theme().
 */
function menu_block_split_theme() {
  return array(
    'menu_block_split_menu' => array(
      'variables' => array(
        'name' => 'navigation',
        'tree' => array(),
        'level' => 0,
      ),
    ),
    'menu_block_split_menu_item' => array(
      'variables' => array(
        'link' => '',
        'has_children' => 0,
        'menu' => '',
        'in_active_trail' => FALSE,
        'extra_class' => NULL,
      ),
    ),
    'menu_block_split_menu_item_link' => array(
      'variables' => array(
        'link' => '',
      ),
    ),
  );
}

/**
 * Theme menu.
 *
 * @param string $name
 *
 * @param array $tree
 *
 * @param int $level
 *
 * @return menu tree
 */
function theme_menu_block_split_menu($variables) {
  $name = $variables['name'];
  $tree = $variables['tree'];
  $level = $variables['level'];
  if ($menu = menu_block_split_render_tree($tree, $level)) {
    return '<ul class="menu">' . $menu . '</ul>';
  }
}

/**
 * override of theme_menu_item to avoid conflict with dhtml_menu module.
 *
 */
function theme_menu_block_split_menu_item($variables) {
  $link = $variables['link'];
  $has_children = $variables['has_children'];
  $menu = $variables['menu'];
  $in_active_trail = $variables['in_active_trail'];
  $extra_class = $variables['extra_class'];
  $class = $menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf');
  if (!empty($extra_class)) {
    $class .= ' ' . $extra_class;
  }
  if ($in_active_trail) {
    $class .= ' active-trail';
  }
  return '<li class="' . $class . '">' . $link . render($menu) . '</li>';
}

/**
 * override of theme_menu_item_link to avoid conflict with dhtml_menu module.
 *
 */
function theme_menu_block_split_menu_item_link($variables) {
  $link = $variables['link'];
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  return l($link['title'], $link['href'], $link['localized_options']);
}

Functions

Namesort descending Description
menu_block_split_block_info Implements hook_block_info().
menu_block_split_block_view Implements hook_block_view().
menu_block_split_count_active_items Count the number of active items in a menu.
menu_block_split_get_first_level Get info about first level.
menu_block_split_help Implements hook_help().
menu_block_split_init Implements hook_init().
menu_block_split_menu Implements hook_menu().
menu_block_split_menu_name Returns the menu_name to which the current menu-item belongs.
menu_block_split_menu_tree_output outputs a menu tree.
menu_block_split_permission Implements hook_permission().
menu_block_split_render_tree Render menu
menu_block_split_settings Settings form.
menu_block_split_settings_validate Settings form validate.
menu_block_split_theme Implementation of hook_theme().
theme_menu_block_split_menu Theme menu.
theme_menu_block_split_menu_item override of theme_menu_item to avoid conflict with dhtml_menu module.
theme_menu_block_split_menu_item_link override of theme_menu_item_link to avoid conflict with dhtml_menu module.