Default menu option when item in multiple blocks

jordanlewin - August 18, 2008 - 00:41
Project:Local Menu
Version:6.x-1.5
Component:Code
Category:bug report
Priority:normal
Assigned:Unassigned
Status:reviewed & tested by the community
Description

When an item appears in multiple menus, currently the Local Menu module doesn't know which menu to make the active menu for that item/page and therefore display the proper links in the block. For example, I have a page that appears in both the 'primary-links' menu as well as in a custom 'menu-utility-links' menu that I created. By default the module just shows the first menu it finds, but this often results in the proper menu links not being showed in the block on this page. In this case, I want it to show the relative/local links from the 'primary-links' menu, not the other custom one (because there are none). I've altered the code to create a "Default Menu" option on the block configuration page so that you can set which menu it should default to when there is more than one for a particular item. If other pages don't belong to this menu, no problem, they'll select the menu they belong to. This is not a real patch, but here's the code that I've altered. Search for // PATCH AND // END PATCH to see where I've altered the code.

<?php
// $Id: local_menu.module,v 1.7 2008/03/19 11:27:00 fokke Exp $

define('LOCAL_MENU_TOP', 1);
define('LOCAL_MENU_PARENT', 10);
define('LOCAL_MENU_FAMILY', 11);
define('LOCAL_MENU_CHILDREN', 12);
define('LOCAL_MENU_UNLIMITED', 99);
// PATCH
define('LOCAL_MENU_DEFAULT_MENU', 'primary-links');
// END PATCH

function local_menu_block($op = 'list', $delta = 0, $edit = array()) {

  if (
$op == 'list') {
       
$blocks[0] = array(
         
'info'       => t('Local Menu'),
        );
       
        return
$blocks;
    }
   
    switch (
$op) {
       
    case
'configure':
     
// PATCH TO ALLOW TO SPECIFY DEFAULT MENU WHEN AN ITEM SHOWS UP IN MORE THAN ONE MENU
           
$form['local_menu_default_menu'] = array(    
       
'#type' => 'textfield',
       
'#title' => t('Default Menu'),
       
'#description' => t('Enter the computer readable name for the menu this block should display if an item shows up in more than one menu. By default this is set to "primary-links".'),
       
'#default_value' => variable_get('local_menu_default_menu', LOCAL_MENU_DEFAULT_MENU),
      );
           
// END PATCH
     
$form['local_menu_start'] = array(
       
'#type' => 'select',
       
'#title' => t('Starting depth'),
       
'#description' => t('At what depth we need to start draw the menu.'),
       
'#options' => array(
           
LOCAL_MENU_TOP => t('Top level (like a normal menu)'),
           
2 => t('Level #2'),
           
3 => t('Level #3'),
           
4 => t('Level #4'),
           
LOCAL_MENU_PARENT => t('Parent depth (of current page)'),
           
LOCAL_MENU_FAMILY => t('Current depth'),
           
LOCAL_MENU_CHILDREN => t('One level deeper (children)'),
        ),
       
'#default_value' => variable_get('local_menu_start', 2),
      );
     
$form['local_menu_depth'] = array(
       
'#type' => 'select',
       
'#title' => t('Rendered depth'),
       
'#description' => t('How deep we should allow the menu to be.'),
       
'#options' => array(
           
1 => t('One level (like primary links)'),
           
2 => t('Two levels'),
           
3 => t('Three levels'),
           
LOCAL_MENU_UNLIMITED => t('All levels (unlimited)'),
        ),
       
'#default_value' => variable_get('local_menu_depth', LOCAL_MENU_UNLIMITED),
      );
     
      return
$form;
     
    case
'save':
     
variable_set('local_menu_start', $edit['local_menu_start']);
     
variable_set('local_menu_depth', $edit['local_menu_depth']);
     
// PATCH
     
variable_set('local_menu_default_menu', $edit['local_menu_default_menu']);
           
// END PATCH
     
return;
     
    case
'view':
    default:
       
$item = menu_get_item();
       
       
// Local Task
       
if ($item && $item['tab_root']) {
           
$path_root = preg_replace('!^('.preg_replace('!%[^/]*!', '[^/]+', $item['tab_root']).').*$!', '\\1', $item['href']);
               
$item = menu_get_item($path_root);
        }
           
//dpr($item);
       
        // Not found
       
if (!$item) {
            return
FALSE;
        }
       
       
// Get the menu link and set the active menu to the menu it's in, so Drupal can find it's way and make correct breadcrumbs at the same time
        // PATCH TO NOT SELECT ADMIN MENU AS ACTIVE MENU BECAUSE OF CONFLICT AS WELL AS TO ALLOW FOR DEFAULT MENU WHEN LINK IS PART OF TWO OR MORE MENUS
           
if ($mlid = db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s' AND hidden <> 1 AND menu_name = '%s'", $item['href'], variable_get('local_menu_default_menu', LOCAL_MENU_DEFAULT_MENU)))) {
             
$link    = menu_link_load($mlid);
            } else {
             
$link    = menu_link_load(db_result(db_query("SELECT mlid FROM {menu_links} WHERE link_path = '%s' AND hidden <> 1 AND menu_name != 'admin_menu'", $item['href'])));
            }
       
menu_set_active_menu_name($link['menu_name']);
           
// END PATCH
       
        // Set current path temporarily to the root of the possible local task we might be, so Drupal finds it's way
       
$q = $_GET['q'];
       
$_GET['q'] = $item['href'];
       
$tree        = menu_tree_page_data(menu_get_active_menu_name());
       
$_GET['q'] = $q;
       
           
$depth    = variable_get('local_menu_depth', LOCAL_MENU_UNLIMITED);
       
$start    = variable_get('local_menu_start', 2);
       
$title    = db_result(db_query("SELECT title FROM {menu_custom} WHERE menu_name = '%s'", $menu));

        if (
$start == LOCAL_MENU_TOP && $depth == LOCAL_MENU_UNLIMITED) {
               
$block['subject'] = check_plain($title);
               
$block['content'] = menu_tree_output($tree);
               
            } else {
               
            if (
$start == LOCAL_MENU_PARENT) {
               
$start = max(1, $link['depth'] - 1);
               
            } elseif (
$start == LOCAL_MENU_FAMILY) {
               
$start = $link['depth'];
               
            } elseif (
$start == LOCAL_MENU_CHILDREN) {
               
$start = $link['depth'] + 1;
            }
               
               
$block['content'] = local_menu_content($tree, $start, $depth);
               
$block['subject'] = check_plain(($local_title = local_menu_title()) ? $local_title : $title);
            }
           
      return
$block;
  }
}

function
local_menu_content(&$tree, $start, $depth) {   
 
$items    = array();
 
$output    = '';

  foreach (
$tree as $data) {
    if (!
$data['link']['hidden']) {
     
$items[] = $data;
    }
  }

 
$num_items = count($items);
 
  foreach (
$items as $i => $data) {

      if (
$start <= $data['link']['depth']) {
       
$extra_class = NULL;
       
        if (
$i == 0) {
         
$extra_class = 'first';
        }
       
        if (
$i == $num_items - 1) {
         
$extra_class .= ' last';
        }
       
       
$link        = theme('menu_item_link', $data['link']);
       
$below    = ($depth > 1 && $data['below']) ? local_menu_content($data['below'], $start, $depth - 1) : '';
       
$output .= theme('menu_item', $link, $data['link']['has_children'], $below, $data['link']['in_active_trail'], $extra_class);
       
    } elseif (
$data['link']['in_active_trail'] && $data['below']) {

        if (
$start == $data['link']['depth'] + 1) {
           
local_menu_title($data['link']['title']);
        }
       
       
$output = local_menu_content($data['below'], $start, $depth - 1);
    }
  }
 
  if (
$start <= $data['link']['depth']) {
       
$output = $output ? theme('menu_tree', $output) : '';
    }
 
  return
$output;     
}

function
local_menu_title($set_title = '') {
    static
$title;
   
    if (
$set_title) {
       
$title = $set_title;
    }
   
    return
$title;
}
?>

#1

Proct0t - September 14, 2008 - 22:22

subscribing

#2

ztyx - September 20, 2008 - 16:28

This is an alternative solution to #272786: Multiple menu items uncertainty.

#3

robbertnl - December 8, 2008 - 15:27

Is this feature already implemented? Or is a patch available somewhere?
I tried putting this in my local_menu.module but i don't see any difference.
My localmenu is empty when i have a primary and secondary link(which is primary link but 2nd level) linking to the same node

#4

akalsey - December 31, 2008 - 06:57

Attached is a patch that implements this feature.

AttachmentSize
local_menu_select.patch 1.97 KB

#5

akalsey - December 31, 2008 - 07:13

I've changed the patch from above to show a select list with all your menus in it. Instead of needing to type in the name of the menu in the block config, the user can select from a list.

AttachmentSize
local_menu_select-2.patch 2.3 KB

#6

akalsey - December 31, 2008 - 07:14
Status:needs work» needs review

#7

mauricemengel - February 4, 2009 - 22:08

I tried the patch of drupal 6.9 and it works as supposed to. Very nice!

#8

grendzy - April 6, 2009 - 23:15
Status:needs review» reviewed & tested by the community

The patch in #5 worked for me. BTW, this resolves a related bug: #280208: How about menu items that point to a view?

The reason, I think, is that menu items defined by a module get their own "system" entry in the menu_links table.

 
 

Drupal is a registered trademark of Dries Buytaert.