thierry-b
12/16/2014 - 8:40 AM

Add system menu's to a Taxonomy Menu Block. Each menu item is checked for access and the altered tree gets cached. UPDATE: If the current no

Add system menu's to a Taxonomy Menu Block. Each menu item is checked for access and the altered tree gets cached. UPDATE: If the current node isn't part of the tree, the active trail is still set UPDATE2: Implemented the_aim_taxonomy_menu_block_alter_theme_registry_alter(&$theme_registry) to override the theming

<?php
/**
 * @file the_aim_taxonomy_menu_block_alter
 *
 * @description
 * Add the menu items of main-menu to the taxonomy menu block called main-menu
 **/

// Define the TMB to be altered as an serialized array like
// array(vid => array(tbm-delta => array(system-menu, system-menu))).
define(
  'TMB_ALTER', serialize(
    array(
      2 => array(
        1 => array('main-menu'),
        3 => array('main-menu', 'secondary-menu'),
      ),
    )
  )
);
define('TMB_ALTER_CLASSES', TRUE);

/**
 * Implements hook_taxonomy_menu_block_alter().
 *
 * Alters the taxonomy menu block data.
 **/
function the_aim_taxonomy_menu_block_alter_taxonomy_menu_block_alter(&$tree, $config) {
  foreach (unserialize(TMB_ALTER) as $vid => $deltas) {
    if ($config['vid'] == $vid) {
      foreach ($deltas as $delta => $system_menus) {
        // Alter the output of the specified taxonomy menu block.
        if($config['delta'] == $delta) {
          // Get the language object
          global $language;

          // If the active page is a node, get the object for setting the active trail.
          $obj = new stdClass();
          if(arg(0) == 'node') {
            $obj = menu_get_object();

            // Find parents
            $parent_candidates = _the_aim_mtbp_get_parent_candidates(drupal_get_path_alias());
            // Don't even bother if current page is root
            if (!empty($parent_candidates)) {
              // Find link items matching the parent candidates in all menus
              $matched_menus = array();
              $matched_link_titles = array();
              $results = db_select('menu_links', 'ml')
                  ->fields('ml', array('link_path'))
                  ->condition('link_path', $parent_candidates, 'IN')
                  ->execute()->fetchCol();

              if(!empty($results)) {
                $obj->the_aim_mtbp = $results;
              }
            }
          }

          // Add each system menu to the tmb
          foreach($system_menus as $system_menu) {
            // Get the build info from the system menu.
            $menu_build = _menu_build_tree($system_menu);
            $menu_build['menu_links'] = array();
            // Add the menu link ids and their weights
            foreach ($menu_build['tree'] as $mlid => $mitem) {
              if (isset($mitem['link']['weight'])) {
                $menu_build['menu_links'][$mlid] = $mitem['link']['weight'];
              }
            }
            // Sort the menu links by their weight
            asort($menu_build['menu_links'], SORT_NUMERIC);
            // BYPASS THE CHECK ACCESS, RELATED ISSUE https://drupal.org/node/1697570
            // // Check access for the current user to each item in the tree.
            // menu_tree_check_access($menu_build['tree'], $menu_build['node_links']);

            // Transform the menu items into tmb menu items.
            foreach ($menu_build['menu_links'] as $mlid => $weight) {
              $menu_item = $menu_build['tree'][$mlid];
              // For multilingual menu's, check the menu item's language
              if(isset($menu_item['link']['language'])) {
                if($menu_item['link']['language'] == $language->language) {
                  the_aim_taxonomy_menu_block_alter_tmb_transform_menu_item($menu_item, $tree, $menu_build, 0, $config['depth'], $obj);
                }
              }
              else {
                the_aim_taxonomy_menu_block_alter_tmb_transform_menu_item($menu_item, $tree, $menu_build, 0, $config['depth'], $obj);
              }
            }
          }
        }
      }
    }
  }
}

/**
 * Transform a regular menu item to a tmb menu item.
 **/
function the_aim_taxonomy_menu_block_alter_tmb_transform_menu_item($menu_item, &$tree, $menu_build, $depth = 0, $max_depth = 8, $obj) {
  // Set the menu item's parent
  $parents = array('0');
  if (isset($menu_build['menu_links'][$menu_item['link']['plid']])) {
    $parents[0] = 'main_menu_mlid_' . $menu_item['link']['plid'];
  }

  // Set the active trail
  $active_trail = 0;
  // If the active item is a node, check if this menu item matches it.
  if (isset($obj->nid)) {
    if ($menu_item['link']['link_path'] == 'node/' . $obj->nid) {
      // Setting the active trail to 2 gives the list item the class active.
      $active_trail = 2;

      // If the item has a parent, add the active-trail class
      if($parents[0] <> 0) {
        the_aim_taxonomy_menu_block_alter_tbm_active_trail($menu_build['node_links'][$menu_item['link']['plid']], $tree);
      }
    }
    elseif (isset($obj->the_aim_mtbp) && in_array($menu_item['link']['link_path'], $obj->the_aim_mtbp)) {
      $active_trail = 1;
    }
  }

  // Create the new tmb menu item
  $tree['main_menu_mlid_'.$menu_item['link']['mlid']] = array(
    'name' => $menu_item['link']['link_title'],
    'path' => drupal_get_path_alias($menu_item['link']['link_path']),
    'depth' => $depth++,
    'parents' => $parents,
    'active_trail' => $active_trail,
  );

  // Add system menu class
  if (TMB_ALTER_CLASSES) {
    $tree['main_menu_mlid_'.$menu_item['link']['mlid']]['attributes'] = array(
      'class' => array($menu_item['link']['menu_name'] . '-item'),
    );
  }

  // Create the deeper levels if the maximum depth is not reached.
  if(!empty($menu_item['below']) && $depth < $max_depth) {
    foreach ($menu_item['below'] as $child_menu_item) {
      the_aim_taxonomy_menu_block_alter_tmb_transform_menu_item($child_menu_item, $tree, $menu_build, $depth, $max_depth, $obj);
    }
  }
}

/**
 * Set the parents active trail.
 **/
function the_aim_taxonomy_menu_block_alter_tbm_active_trail($parent, &$tree) {
  // Setting active trail to 1 gives the list class the class active-trail.
  $tree[$parent]['active_trail'] = 1;
  // Prevent the top level from going deeper
  if($tree[$parent]['parents'][0] <> 0) {
    the_aim_taxonomy_menu_block_alter_tbm_active_trail($tree[$parent]['parents'][0], $tree);
  }
}

/**
 * Implement hook_theme_registry_alter().
 */
function the_aim_taxonomy_menu_block_alter_theme_registry_alter(&$theme_registry) {
  $theme_registry['taxonomy_menu_block']['function'] = 'theme_the_aim_taxonomy_menu_block_alter';
  $theme_registry['taxonomy_menu_block']['theme path'] = drupal_get_path('module', 'the_aim_taxonomy_menu_block_alter');
}

function theme_the_aim_taxonomy_menu_block_alter($variables) {
  $tree = $variables['items'];
  $config = $variables['config'];

  $num_items = count($tree);
  $i = 0;

  $output = '<ul>';
  foreach ($tree as $tid => $term) {
    $i++;
    // Add classes.
    $attributes = array();
    $link_attributes = array();
    if (isset($term['attributes'])) {
      $attributes += $term['attributes'];
    }
    if ($i == 1) {
      $attributes['class'][] = 'first';
    }
    if ($i == $num_items) {
      $attributes['class'][] = 'last';
    }
    if ($term['active_trail'] == '1') {
      $attributes['class'][] = 'active-trail';
      $link_attributes['class'][] = 'active-trail';
    }
    if ($term['active_trail'] == '2') {
      $attributes['class'][] = 'active';
      $link_attributes['class'][] = 'active';
    }
    $attributes['class'][] = ($i%2) ? 'odd' : 'even';

    // Alter link text if we have to display the nodes attached.
    if (isset($term['nodes'])) {
      $term['name'] = $term['name'] . ' (' . $term['nodes'] . ')';
    }

    // Set alias option to true so we don't have to query for the alias every
    // time, as this is cached anyway.
    $output .= '<li' . drupal_attributes($attributes) . '>';
    $output .= l($term['name'], $term['path'], array('alias' => TRUE, 'attributes' => $link_attributes));
    if (!empty($term['children'])) {
      $output .= theme('taxonomy_menu_block__' . $config['delta'], (array('items' => $term['children'], 'config' => $config)));
    }
    $output .= '</li>';
  }
  $output .= '</ul>';

  return $output;
}
name = the AIM taxonomy menu block alter
description = Add system menus to a taxonomy menu block
core = 7.x

package = the AIM
dependencies[] = taxonomy_menu_block
dependencies[] = the_aim_mtbp
version = 7.x-1.0