By pelsdyret on
I need to hide some main menu items which should only be shown under some specific circumstances.
I cannot use hook_menu_alter() because it has to be decided dynamically if the menu item should be shown or not.
I cannot alter permissions either, because the user should have access to the specific page even though there is no menu link for it; also, it could be an external link.
Do you guys have any other idea? Maybe using a theming function to hide a menu item?
Since I have been struggling with this for hours now, I hope to get some advice. Thanks.
Comments
You can use the
You can use the hook_menu_alter() with access callback properties to check your condition.
hook_menu_alter() is not the answer
Thanks, imranweb, for the input. But, as I wrote, I cannot rely on permissions (or access callback) because the menu item has to be switched off and on dynamically, and not just when the menu is rebuilt. Also, an item may point to an external site.
For now on, I have implemented it in template.php, but I am not sure if it's the best way to do it:
Since this will only work with a specific theme, I would prefer to handle it elsewhere.
Really...try the access callback
The access callback (specified in hook_menu()) can be a custom function that dynamically returns different values, depending on the situation. If it returns FALSE, the menu item disappears. It doesn't have to rely on permissions at all. That's exactly what you want, right? I believe that it gets called on each page build. It's worth a try.
Now, if you're actually reconstructing the menu structure instead of just hiding and unhiding items, the menu has to be rebuilt anyway whenever you change it, right? If you're doing that, you might find it useful to call menu_rebuild() when something interesting changes.
I'm not sure how best to link to an external URL via Drupal's menu system, but a page callback with a drupal_goto() seems like an obvious choice.
--
www.ztwistbooks.com. Math books that are actually fun.
Is this your own menu or an existing one?
Not entirely clear in your post: Are you talking about showing/hiding your own menu item, or some already existing one? If it's your own, then DanZ has it right. You can specify
"access callback"and"access arguments"when specifying your menus inhook_menu(). Yes, your access function will be called on each and every page load where the menu might appear. If the access function returns TRUE, the menu will appear. If FALSE, it won't.You access function can use permissions as one thing it checks to make its decision, but it can do other things, too. It might be based on one of your own configuration settings. It might be based on something in the node being displayed. Whatever is appropriate for what you want to do.
I use the following to
I use the following to dynamically change the css which in turn hides the menu.
Using CSS
Thank you garf. I was thinking about something similar myself.
But it's not very easy to hide only some specific menu items depending on a given criteria. I don't want the entire menu to be hidden.
I could of course give each menu item a css class corresponding to its link value, and then hide those classes, but then I prefer the solution mentioned above, which involves not rendering the items.
Own menu
Thank you for spending time on this issue, it's appreciated.
I have control over the entire menu, meaning that I could implement it as you suggest.
I probably need to clarify a thing. The same user will in some circumstances see the menu link, but in others he won't depending on which part of the site he's visiting at any given moment.
As far as I understand, if I use menu_access and set a specific path to be inaccessible, it will correctly not be shown in the menu, but then again, the user will not be able to access the page directly by entering the url or from a different internal link. I need the menu item to be invisible under some circumstances, but even though it is invisible, the page it points to should work as expected.
Also, I believe that if the menu link points to an external site, hook_menu() is not the answer.
It still should work. Well, maybe.
If the menu you define in
hook_menu()is, say,"node/%node/mymodule/myitem", with a custom access function (your function will need to know which menu item and which node are being queried), your access function only controls display of that specific menu item. The user will see the node, or not, regardless of what your menu does; access to the node itself is a whole different question.You access function can consider the user making the call and any other state information it needs. If you want the menu to only appear between 10 and 11 am, you can do that.
But again, that won't affect the page itself.
Your comment about an external link throws me a bit, though. I haven't had to do external links myself, so I'm not sure. How do you do that? If you're setting a
page_callback()inhook_menu(), and the callback returns a redirect to the external page, it ought to work.Closing
I believe this post has a satisfying reply, so I'll mark it as solved. Thank you.
But one final question...
I'm curious about the external link issue. Did hook_menu() and an access function work for the external link, or did you have to do something else?
Working solution
The only way to change (alter) item in menu tree, including any dynamic values, before the item is rendered (not created or updated) is to use hook_translated_menu_link_alter(). This is the only hook that runs after item processing, but before item render. But, due to performance issues, it runs only on items that have $item['options']['alter'] = TRUE. So to make it work, 'alter' should be set to TRUE programmatically.
This allows not only to work around standard menu access callbacks and implement your own ones, but also change values of menu $item['href'] or any other property.
Founder, Software Engineer | www.drevops.com
Interesting approach, alex
Interesting approach, alex.designworks. Thanks for sharing this.
Yes, the solution really
Yes, the solution really works.
Thanks alex.designworks!!!
-- Pratip Ghosh
i tried but not working
i tried but not working
https://www.drupal.org/project/image_captcha_indicator
https://www.drupal.org/project/ext_js
great approach, thanks.
great approach, thanks.