You are here

submenutree.module in Submenu Tree 7.2

Same filename and directory in other branches
  1. 5 submenutree.module
  2. 6 submenutree.module
  3. 7 submenutree.module

Primarily Drupal hooks and processing the Submenu Tree display.

File

submenutree.module
View source
<?php

/**
 * @file
 * Primarily Drupal hooks and processing the Submenu Tree display.
 */
define('SUBMENUTREE_DISPLAY_MENU', 0);
define('SUBMENUTREE_DISPLAY_TITLES', 1);
define('SUBMENUTREE_DISPLAY_VIEW_MODE', 2);
define('SUBMENUTREE_DISPLAY_BLOCK_MASK', 15);
define('SUBMENUTREE_DISPLAY_BLOCK_MENU', 16);
define('SUBMENUTREE_DISPLAY_BLOCK_TITLES', 17);
define('SUBMENUTREE_DISPLAY_BLOCK_VIEW_MODE', 18);
define('SUBMENUTREE_BLOCK_SUBMENU', 0);
define('SUBMENUTREE_BLOCK_SIBLINGMENU', 1);

/**
 * Implements hook_permission().
 */
function submenutree_permission() {
  return array(
    'administer submenu tree settings' => array(
      'title' => t('Administer submenu tree settings'),
      'description' => t('Allows users to configure Submenu Tree settings.'),
    ),
    'administer sub content' => array(
      'title' => t('Administer sub content'),
      'description' => t('Allows users to enable and disable sub content.'),
    ),
    'administer sub content title' => array(
      'title' => t('Administer sub content title'),
    ),
    'administer sub content display type' => array(
      'title' => t('Administer sub content display type'),
    ),
    'administer sub content view mode' => array(
      'title' => t('Administer sub content view mode'),
    ),
    'administer sibling content' => array(
      'title' => t('Administer sibling content'),
      'description' => t('Allows users to enable and disable sibling content.'),
    ),
    'administer sibling content title' => array(
      'title' => t('Administer sibling content title'),
    ),
    'administer sibling content display type' => array(
      'title' => t('Administer sibling content display type'),
    ),
    'administer sibling content view mode' => array(
      'title' => t('Administer sibling content view mode'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function submenutree_menu() {
  $items['admin/config/content/submenu-tree'] = array(
    'access arguments' => array(
      'administer submenu tree settings',
    ),
    'description' => 'Configure Submenu Tree settings.',
    'file' => 'submenutree.admin.inc',
    'page arguments' => array(
      'submenutree_configuration_form',
    ),
    'page callback' => 'drupal_get_form',
    'title' => 'Submenu Tree',
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

/**
 * Implements hook_help().
 */
function submenutree_help($path, $arg) {
  switch ($path) {
    case 'admin/config/content/submenu-tree':
      $output = '';
      $output .= '<p>' . t('Configure Submenu Tree settings.') . '</p>';
      return $output;
  }
}

/**
 * Implements hook_form_alter().
 */
function submenutree_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'node_type_form' || !empty($form['#node_edit_form']) && variable_get('submenutree_node_type_' . $form['type']['#value'], 0)) {
    $form['submenutree'] = array(
      '#type' => 'fieldset',
      '#group' => 'additional_settings',
      '#title' => t('Sub and Sibling content'),
      '#attached' => array(
        'js' => array(
          drupal_get_path('module', 'submenutree') . '/submenutree.js',
        ),
      ),
      '#attributes' => array(
        'class' => array(
          'node-form-submenutree-settings',
        ),
      ),
    );
    $form['submenutree']['submenutree_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Display sub content'),
    );
    $form['submenutree']['submenutree_container'] = array(
      '#type' => 'container',
    );
    $form['submenutree']['submenutree_container']['submenutree_title'] = array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      '#description' => t('The title of the sub content and sub content block.'),
    );
    $form['submenutree']['submenutree_container']['submenutree_display'] = array(
      '#type' => 'select',
      '#title' => t('Display type'),
      '#options' => array(
        'content' => array(
          SUBMENUTREE_DISPLAY_MENU => t('Menu'),
          SUBMENUTREE_DISPLAY_TITLES => t('Titles only'),
          SUBMENUTREE_DISPLAY_VIEW_MODE => t('Select view mode'),
        ),
        'block' => array(
          SUBMENUTREE_DISPLAY_BLOCK_MENU => t('Menu'),
          SUBMENUTREE_DISPLAY_BLOCK_TITLES => t('Titles only'),
          SUBMENUTREE_DISPLAY_BLOCK_VIEW_MODE => t('Select view mode'),
        ),
      ),
      '#description' => t('Select where and how the sub content should be displayed.'),
    );
    $entity_info = entity_get_info('node');
    foreach ($entity_info['view modes'] as $view_mode => $view_mode_info) {
      $view_modes[$view_mode] = $view_mode_info['label'];
    }
    $form['submenutree']['submenutree_container']['submenutree_view_mode'] = array(
      '#type' => 'select',
      '#title' => t('View mode'),
      '#description' => t('Select a the view mode to render the menu items in.'),
      '#options' => $view_modes,
      '#states' => array(
        'visible' => array(
          ':input[name="submenutree_display"]' => array(
            'value' => SUBMENUTREE_DISPLAY_VIEW_MODE,
          ),
        ),
      ),
    );
    $form['submenutree']['submenutree_container']['submenutree_links'] = array(
      '#type' => 'checkbox',
      '#title' => t('Show links'),
      '#states' => array(
        'visible' => array(
          ':input[name="submenutree_display"]' => array(
            'value' => SUBMENUTREE_DISPLAY_VIEW_MODE,
          ),
        ),
      ),
    );
    $form['submenutree']['siblingmenutree_enable'] = array(
      '#type' => 'checkbox',
      '#title' => t('Display sibling content'),
      '#default_value' => !empty($node->siblingmenutree_enable),
    );
    $form['submenutree']['siblingmenutree_container'] = array(
      '#type' => 'container',
    );
    $form['submenutree']['siblingmenutree_container']['siblingmenutree_title'] = array(
      '#type' => 'textfield',
      '#title' => t('Title'),
      '#description' => t('The title of the sibling content and sibling content block.'),
    );
    $form['submenutree']['siblingmenutree_container']['siblingmenutree_display'] = array(
      '#type' => 'select',
      '#title' => t('Display type'),
      '#options' => array(
        'content' => array(
          SUBMENUTREE_DISPLAY_MENU => t('Menu'),
          SUBMENUTREE_DISPLAY_TITLES => t('Titles only'),
          SUBMENUTREE_DISPLAY_VIEW_MODE => t('Select view mode'),
        ),
        'block' => array(
          SUBMENUTREE_DISPLAY_BLOCK_MENU => t('Menu'),
          SUBMENUTREE_DISPLAY_BLOCK_TITLES => t('Titles only'),
          SUBMENUTREE_DISPLAY_BLOCK_VIEW_MODE => t('Select view mode'),
        ),
      ),
      '#description' => t('Select where and how the sibling content should be displayed.'),
    );
    $form['submenutree']['siblingmenutree_container']['siblingmenutree_view_mode'] = array(
      '#type' => 'select',
      '#title' => t('View mode'),
      '#description' => t('Select a the view mode to render the menu items in.'),
      '#options' => $view_modes,
      '#states' => array(
        'visible' => array(
          ':input[name="siblingmenutree_display"]' => array(
            'value' => SUBMENUTREE_DISPLAY_VIEW_MODE,
          ),
        ),
      ),
    );
    $form['submenutree']['siblingmenutree_container']['siblingmenutree_links'] = array(
      '#type' => 'checkbox',
      '#title' => t('Show links'),
      '#states' => array(
        'visible' => array(
          ':input[name="siblingmenutree_display"]' => array(
            'value' => SUBMENUTREE_DISPLAY_VIEW_MODE,
          ),
        ),
      ),
    );

    // Default values and access restrictions when editing content types
    if ($form_id == 'node_type_form') {

      // Restrict access to Submenu Tree configuration settings
      $form['submenutree']['#access'] = user_access('administer submenu tree settings');

      // Add a set of radio buttons to indicate which content types should have submenu tree options added
      $form['submenutree']['submenutree_node_type'] = array(
        '#type' => 'radios',
        '#title' => t('Submenu Tree'),
        '#default_value' => variable_get('submenutree_node_type_' . $form['#node_type']->type, 0),
        '#options' => array(
          1 => t('Enabled'),
          0 => t('Disabled'),
        ),
        '#description' => t('Enable or disable Submenu Tree for this node type.'),
        '#weight' => -50,
      );

      // Set content type specific sub content settings
      $form['submenutree']['submenutree_enable']['#default_value'] = variable_get('submenutree_enable_' . $form['#node_type']->type, 0);
      $form['submenutree']['submenutree_enable']['#states'] = array(
        'visible' => array(
          ':input[name="submenutree_node_type"]' => array(
            'value' => 1,
          ),
        ),
      );
      $form['submenutree']['submenutree_container']['#states'] = array(
        'visible' => array(
          ':input[name="submenutree_node_type"]' => array(
            'value' => 1,
          ),
        ),
      );
      $form['submenutree']['submenutree_container']['submenutree_title']['#default_value'] = variable_get('submenutree_title_' . $form['#node_type']->type, '');
      $form['submenutree']['submenutree_container']['submenutree_display']['#default_value'] = variable_get('submenutree_display_' . $form['#node_type']->type, SUBMENUTREE_DISPLAY_MENU);
      $form['submenutree']['submenutree_container']['submenutree_view_mode']['#default_value'] = variable_get('submenutree_view_mode_' . $form['#node_type']->type, 'full');
      $form['submenutree']['submenutree_container']['submenutree_links']['#default_value'] = variable_get('submenutree_links_' . $form['#node_type']->type, FALSE);

      // Set content type specific sibling content settings
      $form['submenutree']['siblingmenutree_enable']['#default_value'] = variable_get('siblingmenutree_enable_' . $form['#node_type']->type, 0);
      $form['submenutree']['siblingmenutree_enable']['#states'] = array(
        'visible' => array(
          ':input[name="submenutree_node_type"]' => array(
            'value' => 1,
          ),
        ),
      );
      $form['submenutree']['siblingmenutree_container']['#states'] = array(
        'visible' => array(
          ':input[name="submenutree_node_type"]' => array(
            'value' => 1,
          ),
        ),
      );
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_title']['#default_value'] = variable_get('siblingmenutree_title_' . $form['#node_type']->type, '');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_display']['#default_value'] = variable_get('siblingmenutree_display_' . $form['#node_type']->type, SUBMENUTREE_DISPLAY_MENU);
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_view_mode']['#default_value'] = variable_get('siblingmenutree_view_mode_' . $form['#node_type']->type, 'full');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_links']['#default_value'] = variable_get('siblingmenutree_links_' . $form['#node_type']->type, FALSE);
    }

    // Default values and access restrictions when editing nodes
    if (!empty($form['#node_edit_form'])) {

      // Node
      $node = $form['#node'];

      // Restrict access to the node's sub/sibling content settings
      $form['submenutree']['#access'] = user_access('administer sub content') || user_access('administer sibling content');

      // Set node specific sub content settings
      $form['submenutree']['submenutree_enable']['#access'] = user_access('administer sub content');
      $form['submenutree']['submenutree_container']['submenutree_title']['#access'] = user_access('administer sub content title');
      $form['submenutree']['submenutree_container']['submenutree_display']['#access'] = user_access('administer sub content display type');
      $form['submenutree']['submenutree_container']['submenutree_view_mode']['#access'] = user_access('administer sub content view mode');
      $form['submenutree']['submenutree_container']['submenutree_links']['#access'] = user_access('administer sub content view mode');
      $form['submenutree']['submenutree_enable']['#default_value'] = isset($node->submenutree_enable) ? $node->submenutree_enable : variable_get('submenutree_enable_' . $node->type, 0);
      $form['submenutree']['submenutree_container']['#states'] = array(
        'invisible' => array(
          ':input[name="submenutree_enable"]' => array(
            'checked' => FALSE,
          ),
        ),
      );
      $form['submenutree']['submenutree_container']['submenutree_title']['#default_value'] = isset($node->submenutree_title) ? $node->submenutree_title : variable_get('submenutree_title_' . $node->type, '');
      $form['submenutree']['submenutree_container']['submenutree_display']['#default_value'] = isset($node->submenutree_display) ? $node->submenutree_display : variable_get('submenutree_display_' . $node->type, SUBMENUTREE_DISPLAY_MENU);
      $form['submenutree']['submenutree_container']['submenutree_view_mode']['#default_value'] = isset($node->submenutree_view_mode) ? $node->submenutree_view_mode : variable_get('submenutree_view_mode_' . $node->type, 'full');
      $form['submenutree']['submenutree_container']['submenutree_links']['#default_value'] = isset($node->submenutree_links) ? $node->submenutree_links : variable_get('submenutree_links_' . $node->type, FALSE);

      // Set node type specific sibling content settings
      $form['submenutree']['siblingmenutree_enable']['#access'] = user_access('administer sibling content');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_title']['#access'] = user_access('administer sibling content title');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_display']['#access'] = user_access('administer sibling content display type');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_view_mode']['#access'] = user_access('administer sibling content view mode');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_links']['#access'] = user_access('administer sibling content view mode');
      $form['submenutree']['siblingmenutree_enable']['#default_value'] = isset($node->siblingmenutree_enable) ? $node->siblingmenutree_enable : variable_get('siblingmenutree_enable_' . $node->type, 0);
      $form['submenutree']['siblingmenutree_container']['#states'] = array(
        'invisible' => array(
          ':input[name="siblingmenutree_enable"]' => array(
            'checked' => FALSE,
          ),
        ),
      );
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_title']['#default_value'] = isset($node->siblingmenutree_title) ? $node->siblingmenutree_title : variable_get('siblingmenutree_title_' . $node->type, '');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_display']['#default_value'] = isset($node->siblingmenutree_display) ? $node->siblingmenutree_display : variable_get('siblingmenutree_display_' . $node->type, SUBMENUTREE_DISPLAY_MENU);
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_view_mode']['#default_value'] = isset($node->siblingmenutree_view_mode) ? $node->siblingmenutree_view_mode : variable_get('siblingmenutree_view_mode_' . $node->type, 'full');
      $form['submenutree']['siblingmenutree_container']['siblingmenutree_links']['#default_value'] = isset($node->siblingmenutree_links) ? $node->siblingmenutree_links : variable_get('siblingmenutree_links_' . $node->type, FALSE);
    }
  }
}

/**
 * Implements hook_node_load().
 */
function submenutree_node_load($nodes, $types) {
  $schema = drupal_get_schema('node_submenutree');
  $result = db_select('node_submenutree')
    ->fields('node_submenutree')
    ->condition('nid', array_keys($nodes), 'IN')
    ->execute();
  foreach ($result as $record) {
    foreach ($schema['fields'] as $field => $unused) {
      $nodes[$record->nid]->{$field} = $record->{$field};
    }
  }
}

/**
 * Implements hook_node_insert().
 */
function submenutree_node_insert($node) {
  submenutree_node_update($node);
}

/**
 * Implements hook_node_update().
 */
function submenutree_node_update($node) {
  if (variable_get('submenutree_node_type_' . $node->type, 0)) {
    $schema = drupal_get_schema('node_submenutree');
    $values = array();
    foreach ($schema['fields'] as $field => $unused) {
      $values[$field] = empty($node->{$field}) ? 0 : $node->{$field};
    }
    db_merge('node_submenutree')
      ->key(array(
      'nid' => $node->nid,
    ))
      ->fields($values)
      ->execute();
  }
  else {
    submenutree_node_delete($node);
  }
}

/**
 * Implements hook_node_delete().
 */
function submenutree_node_delete($node) {
  db_delete('node_submenutree')
    ->condition('nid', $node->nid)
    ->execute();
}

/**
 * Implements hook_node_view().
 */
function submenutree_node_view($node, $view_mode, $langcode) {
  if ($view_mode == 'full' && node_is_page($node) && (!empty($node->submenutree_enable) || !empty($node->siblingmenutree_enable))) {
    $mlid = 0;

    // Other modules may override which mlid to use. Use the first available value.
    foreach (module_implements('submenutree_mlid') as $module) {
      $function = $module . '_submenutree_mlid';
      if ($mlid = $function($node)) {
        break;
      }
    }

    // Else, give priority to the default menu defined by the Menu module.
    // This stanza is from menu_node_prepare()
    if (!$mlid) {

      // Give priority to the default menu
      $menu_name = variable_get('menu_parent_' . $node->type, 'main-menu:0');
      $menu_name = explode(':', $menu_name);
      $menu_name = $menu_name[0];
      $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND menu_name = :menu_name AND module = 'menu' ORDER BY mlid ASC", 0, 1, array(
        ':path' => 'node/' . $node->nid,
        ':menu_name' => $menu_name,
      ))
        ->fetchField();
    }

    // Check all menus if a link does not exist in the default menu.
    if (!$mlid) {
      $mlid = db_query_range("SELECT mlid FROM {menu_links} WHERE link_path = :path AND module = 'menu' ORDER BY mlid ASC", 0, 1, array(
        ':path' => 'node/' . $node->nid,
      ))
        ->fetchField();
    }
    if ($mlid) {
      $item = menu_link_load($mlid);
      $tree = menu_tree_all_data($item['menu_name'], $item);

      // Traverse down the tree to find our node, following in_active_trial
      // This code stanza is loosely inspired by menu_set_active_trail()
      $my_tree = FALSE;
      $parent_tree = FALSE;
      $curr = current($tree);
      $key = key($tree);
      while ($curr) {
        if ($curr['link']['href'] == $item['href']) {
          $my_tree = $curr['below'];
          $parent_tree = $tree;

          // Remove the current node from the parent tree, since we only want to
          // display the siblings from the same level.
          unset($parent_tree[$key]);
          $curr = FALSE;
        }
        else {

          // Move to the child link if it's in the active trail.
          if ($curr['below'] && $curr['link']['in_active_trail']) {
            $tree = $curr['below'];
          }
          $key = key($tree);
          $curr = current($tree);
          next($tree);
        }
      }

      // Sanity check that we did find something
      if ($my_tree && $node->submenutree_enable) {
        _submenutree_menutree_view($node, 'submenutree', $my_tree);
      }
      if ($parent_tree && $node->siblingmenutree_enable) {
        _submenutree_menutree_view($node, 'siblingmenutree', $parent_tree);
      }
    }
  }
}

/**
 * Implements of hook_block_info().
 */
function submenutree_block_info() {
  $blocks[SUBMENUTREE_BLOCK_SUBMENU] = array(
    'info' => t('Sub content'),
    'cache' => DRUPAL_CACHE_PER_PAGE,
  );
  $blocks[SUBMENUTREE_BLOCK_SIBLINGMENU] = array(
    'info' => t('Sibling content'),
    'cache' => DRUPAL_CACHE_PER_PAGE,
  );
  $blocks[2] = array(
    'info' => t('Extended menu links'),
    'cache' => DRUPAL_CACHE_PER_PAGE,
  );
  return $blocks;
}

/**
 * Implements of hook_block_view().
 */
function submenutree_block_view($delta = '') {
  switch ($delta) {
    case SUBMENUTREE_BLOCK_SUBMENU:
    case SUBMENUTREE_BLOCK_SIBLINGMENU:
      return _submenutree_get_block_content($delta);
      break;
    case 2:
      return _submenutree_block_extended_links();
  }
}

/**
 * Implements hook_theme().
 */
function submenutree_theme($existing, $type, $theme, $path) {
  return array(
    'submenu_tree_menu' => array(
      'variables' => array(
        'tree' => NULL,
        'title' => '',
      ),
      'file' => 'submenutree.theme.inc',
    ),
    'submenu_tree_titles' => array(
      'variables' => array(
        'items' => NULL,
        'title' => '',
      ),
      'file' => 'submenutree.theme.inc',
    ),
    'submenu_tree_view_mode' => array(
      'variables' => array(
        'items' => NULL,
        'title' => '',
        'links' => FALSE,
        'view_mode' => 'full',
      ),
      'file' => 'submenutree.theme.inc',
    ),
  );
}

/**
 * View the menu tree, either by poking into $node->content, or via the block functions
 *
 * @param $node
 *   The node being operated upon. This is also used for configuration information.
 * @param $type
 *   The type of menu to produce, either "submenutree" or "siblingmenutree"
 * @param $tree
 *   A fragment of a menu tree to be viewed
 */
function _submenutree_menutree_view($node, $type, $tree) {

  // Get configuration from $node, depending on $type
  $config_item = $type . '_title';
  $title = check_plain($node->{$config_item});
  $config_item = $type . '_display';
  $display = intval($node->{$config_item}) & SUBMENUTREE_DISPLAY_BLOCK_MASK;
  $display_in_block = intval($node->{$config_item}) & ~SUBMENUTREE_DISPLAY_BLOCK_MASK;
  $config_item = $type . '_view_mode';
  $view_mode = $node->{$config_item};
  $config_item = $type . '_links';
  $links = $node->{$config_item};

  // Generate the block title
  if ($display_in_block) {
    $block_title = $title;
    if ($block_title == '') {
      $block_title_type = variable_get('submenutree_block_title', 'current_title');
      switch ($block_title_type) {
        case 'leave_blank':
          $block_title = '';
          break;
        case 'content_title':
          $block_title = $node->title;
          break;
        case 'content_menu_direct_parent':
          $menu_trail = menu_get_active_trail($node->nid);

          // Select the title of the menu item directly above the current node
          $direct_parent = prev($menu_trail);
          if ($direct_parent) {
            $block_title = $direct_parent['title'];
          }
          break;
        case 'content_menu_parent':
          $menu_trail = menu_get_active_trail($node->nid);
          $level = variable_get('submenutree_block_title_content_menu_parent_level', 1);

          // Select the title of the menu item at the specified level above the current node
          if ($menu_trail[$level]) {
            $block_title = $menu_trail[$level]['title'];
          }
          break;
      }
    }

    // Wipe out $title so it doesn't get passed into the theme functions
    $title = NULL;
  }
  else {
    if ($title == '') {
      $title = NULL;
    }
  }
  $output = '';
  if ($display == SUBMENUTREE_DISPLAY_MENU) {
    $output = theme('submenu_tree_menu', array(
      'tree' => $tree,
      'title' => $title,
    ));
  }
  else {
    $items = array();
    foreach ($tree as $k => $v) {

      // Check that this is a node view
      if (empty($v['link']['hidden']) && strpos($v['link']['href'], 'node/') === 0) {
        $nid = drupal_substr($v['link']['href'], 5);
        $child = node_load($nid);
        $items[] = array(
          'node' => $child,
          'weight' => $v['link']['weight'],
          'title' => check_plain($v['link']['title']),
        );
      }
    }
    _submenutree_sort_items($items);

    // Now render our links or our nodes
    switch ($display) {
      case SUBMENUTREE_DISPLAY_TITLES:
        $output = theme('submenu_tree_titles', array(
          'items' => $items,
          'title' => $title,
        ));
        break;
      case SUBMENUTREE_DISPLAY_VIEW_MODE:
        $output = theme('submenu_tree_view_mode', array(
          'items' => $items,
          'title' => $title,
          'links' => $links,
          'view_mode' => $view_mode,
        ));
        break;
    }
  }
  if ($output) {
    if ($display_in_block == 0) {
      $node->content['submenutree'] = array(
        '#type' => 'container',
        '#attributes' => array(
          'class' => array(
            'submenutree',
          ),
        ),
        'tree' => array(
          '#markup' => $output,
        ),
      );
    }
    else {
      $blocks_map = array(
        'submenutree' => SUBMENUTREE_BLOCK_SUBMENU,
        'siblingmenutree' => SUBMENUTREE_BLOCK_SIBLINGMENU,
      );
      _submenutree_set_block_content($blocks_map[$type], array(
        'subject' => $block_title,
        'content' => $output,
      ));
    }
  }
}

/**
 * $block should be an array like those used in hook_block
 * ie array('subject' => 'title', 'content' => 'some content');
 */
function _submenutree_set_block_content($delta, $block = NULL) {
  static $stored_content = array(
    SUBMENUTREE_BLOCK_SUBMENU => array(),
    SUBMENUTREE_BLOCK_SIBLINGMENU => array(),
  );
  if (isset($block) && is_array($block)) {
    $stored_content[$delta] = $block;
  }
  return $stored_content[$delta];
}
function _submenutree_get_block_content($delta) {
  return _submenutree_set_block_content($delta);
}

/**
 * Return block of extended links
 */
function _submenutree_block_extended_links() {
  $menu_name = variable_get('submenutree_extended_menu_name', 'main-menu');
  $menu_level = variable_get('submenutree_extended_menu_level', 1);

  // Loosely derived from menu_navigation_links()
  $parent = FALSE;
  $tree = menu_tree_page_data($menu_name);

  // Go down the active trail until the right level is reached.
  while ($menu_level-- > 0 && $tree) {

    // Loop through the current level's items until we find one that is in trail.
    while ($item = array_shift($tree)) {
      if ($item['link']['in_active_trail']) {
        $parent = $item;

        // If the item is in the active trail, we continue in the subtree.
        $tree = empty($item['below']) ? array() : $item['below'];
        break;
      }
    }
  }
  if (!empty($parent)) {
    $title = $parent['link']['title'];
    $output = menu_tree_output($tree);
  }
  if (!empty($output)) {
    $block = array(
      'subject' => $title,
      'content' => $output,
    );
    return $block;
  }
}

/**
 * Sort an array of items.
 *
 * @param $items
 *   The array of items to be sorted.
 */
function _submenutree_sort_items(&$items) {
  usort($items, '_submenutree_sort_items_compare');
}

/**
 * Compare two items by weight then title.
 *
 * @param a
 *   The first item to compare.
 * @param b
 *   The second item to compare.
 * @return
 *   An integer less than, equal to, or greater than zero if $a is considered
 *   to be respectively less than, equal to, or greater than $b.
 */
function _submenutree_sort_items_compare($a, $b) {
  $ret = $a['weight'] - $b['weight'];
  if ($ret == 0) {
    $ret = strcasecmp($a['title'], $b['title']);
  }
  return $ret;
}

/**
 * Implements hook_field_extra_fields().
 */
function submenutree_field_extra_fields() {
  $extra = array();
  foreach (array_keys(node_type_get_names()) as $type) {
    $extra['node'][$type] = array(
      'display' => array(
        'submenutree' => array(
          'label' => t('Submenu tree'),
          'weight' => 0,
        ),
      ),
    );
  }
  return $extra;
}

Functions

Namesort descending Description
submenutree_block_info Implements of hook_block_info().
submenutree_block_view Implements of hook_block_view().
submenutree_field_extra_fields Implements hook_field_extra_fields().
submenutree_form_alter Implements hook_form_alter().
submenutree_help Implements hook_help().
submenutree_menu Implements hook_menu().
submenutree_node_delete Implements hook_node_delete().
submenutree_node_insert Implements hook_node_insert().
submenutree_node_load Implements hook_node_load().
submenutree_node_update Implements hook_node_update().
submenutree_node_view Implements hook_node_view().
submenutree_permission Implements hook_permission().
submenutree_theme Implements hook_theme().
_submenutree_block_extended_links Return block of extended links
_submenutree_get_block_content
_submenutree_menutree_view View the menu tree, either by poking into $node->content, or via the block functions
_submenutree_set_block_content $block should be an array like those used in hook_block ie array('subject' => 'title', 'content' => 'some content');
_submenutree_sort_items Sort an array of items.
_submenutree_sort_items_compare Compare two items by weight then title.

Constants