Active
Project:
Menu Attach Block
Version:
7.x-1.11
Component:
Code
Priority:
Major
Category:
Bug report
Assigned:
Reporter:
Created:
4 May 2014 at 15:18 UTC
Updated:
4 Mar 2015 at 11:46 UTC
Jump to comment: Most recent
At present, function menu_attach_block_link(&$variables) has no logic in place to hide from being rendered as a link should the rendered $block ($block_output) be empty. The most common scenario I could think of where this would occur is where a block requires an authenticated user to display anything.
I suppose a straightforward fix would be to return; nothing should a block's output be empty and the path be entered as '<block>'. This of course won't prevent the
e.g. Note the addition of
elseif ($variables['path'] == '<block>') {
return; //No need to display a link to http://yoursite.com/<block>
}
function menu_attach_block_link(&$variables) {
$block = FALSE;
$options = $variables['options'];
if (isset($options['menu_attach_block']) && !empty($options['menu_attach_block']['name'])) {
$block = menu_attach_block_load_from_key($options['menu_attach_block']['name']);
}
// Render a block if one is attached to this link.
if ($block) {
$link = '';
// Render the link with the block content afterwards.
if ($variables['path'] != '<block>') {
// Build the link manually instead of using l() to avoid getting caught in
// theme_link() again.
$link = '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</a>';
$attributes = array(
'class' => 'menu-attach-block-drop-link',
'id' => $variables['path'] . '-drop-link-' . $variables['options']['menu_attach_block']['mlid'],
);
// Pass a space as the fragment parameter to get a <a href='# '> link.
// @link http://bit.ly/zZXArS @endlink
$l_options = array(
'fragment' => ' ',
'external' => TRUE,
'attributes' => $attributes,
);
$link .= PHP_EOL . l(t('More'), '', $l_options);
}
// Get the block html.
$block_output = menu_attach_block_block_render($block['module'], $block['delta']);
if (!empty($block_output)) {
$variables = array(
'orientation' => $options['menu_attach_block']['orientation'],
'content' => $block_output,
);
$block_output = theme('menu_attach_block_wrapper', $variables);
return $link . $block_output;
} elseif ($variables['path'] == '<block>') {
return; //No need to display a link to http://yoursite.com/<block>
}
}
// Otherwise, pass through to the original theme function.
return theme('menu_attach_block_link_default', $variables);
}
Comments
Comment #1
cmonnow commentedUpdated title for clarification.
Comment #2
cmonnow commentedComment #3
cameron tod commentedIn testing this, I think I have actually discovered a larger issue where blocks that shouldn't show to given users are still displayed in the dropdown.
Steps to reproduce (bartik theme):
- Create a simple block, and restrict it so it shows only to auth users
- Add the block to a visible region
- Attach the block to a visible menu item
- While logged in, verify the block appears in the region and in the menu.
- Open a new incognito/private browsing window where you are not logged in
- The block will not show in the visible region but will show in the menu.
Testing now...this will require automated tests I think.
Comment #4
cameron tod commentedComment #5
cmonnow commentedThat's interesting. Does it only occur when you've also added the block to a region as well?
Speaking of my original suggestion, it's probably still not ideal to have the menu item, though empty, added at all. Perhaps it would be more appropriate to simply unset the menu item completely where block rendering fails in menu_attach_block_preprocess_links() upstream - which would require shifting of all the block logic upstream as well.
Speaking of shifting things upstream, both menu_attach_block_preprocess_links() and the later called function, menu_attach_block_link(), are called too late if we wish to embed a form within the menu that may trigger errors (e.g. user login form). $messages is rendered for the page before the links are processed, meaning errors will skip a page load.
I don't know the ideal solution but in my situation I've hacked together a (hook_preprocess_page()) menu_attach_block_preprocess_page() function that attaches the rendered block as a field to the menu item in menu_attach_block items within the main_menu and secondary_menu arrays.
I might post this is a separate issue.