Closed (duplicate)
Project:
Drupal core
Version:
7.x-dev
Component:
base system
Priority:
Normal
Category:
Support request
Assigned:
Unassigned
Reporter:
Created:
30 Sep 2010 at 23:42 UTC
Updated:
2 Oct 2010 at 12:13 UTC
The following code is from _drupal_bootstrap_full() in common.inc:
// Prior to invoking hook_init(), initialize the theme (potentially a custom
// one for this page), so that:
// - Modules with hook_init() implementations that call theme() or
// theme_get_registry() don't initialize the incorrect theme.
// - The theme can have hook_*_alter() implementations affect page building
// (e.g., hook_form_alter(), hook_node_view_alter(), hook_page_alter()),
// ahead of when rendering starts.
menu_set_custom_theme();
drupal_theme_initialize();
module_invoke_all('init');
menu_set_custom_theme() calls menu_get_custom_theme() calls menu_get_item() calls _menu_translate() calls _menu_check_access() before even invoking hook_init()!
I'm working on porting Forum Access to D7, and this is biting me badly. I need to somehow enable the forum moderator to access comment/CID/edit, but this runs into 'access denied' even before hook_init() is called.
Is core really supposed to work this way?
Any ideas on how to get around this limitation?
Related issues:
#768266: menu_get_item shouldn't always check permissions
#768290: Incompatibility with modules implementing hook_init using menu_get_item
Comments
Comment #1
donquixote commentedWhy don't you hook_menu_alter() the ['forum/%'] and ['forum/%/*'] router items, and set your own access callbacks?
This was not possible in D6, where 'forum/123' had a router path 'forum', but this has been changed in D7.
------------
Some thoughts about hook_init() vs menu_get_item():
I was not aware that D7 already has a theme negotiation hook.
I think it makes sense to call menu_get_item() before theme negotiation, but in this case the result should be made available to implementing modules, like this:
Do we really need a theme before hook_init() ? If so, do we need another hook before hook_init() ?
And if we call menu_get_item() before hook_init() in some cases, should we not rather always do it?
Comment #2
donquixote commentedI guess here is where this was introduced:
#553944: Define hook_menu_get_item_alter() as a reliable hook that runs before the page is doomed
Comment #3
salvisI could do that, of course, but it doesn't seem right that I should have to fight so hard and be forced to do my thing even before hook_init(). What if some module wants to go before Forum Access (for whatever reason)? This has a bad smell.
I don't think access callbacks should be called before hook_init(), but maybe I'm wrong — that's why I marked this as support request.
Comment #4
donquixote commentedMaybe we have different ideas of what is an "access callback".
In my book, an access callback is a function that can return TRUE or FALSE, to specify if the user has access or not.
The code that calls the access callback will store the value in $router_item['access'], but it won't do anything about it. Especially, it will not call things like drupal_access_denied() or similar.
I don't think an access callback before hook_init() is a problem. But I could be wrong.
Comment #5
salvisWell, this is not how core currently behaves, nor should it behave that way, because the result might be different once we're past initialization and ready to actually do business. Currently, if the access callback returns FALSE, then drupal_access_denied() is called immediately, before hook_init()! hook_init() never gets called in that case!
Generally, I don't expect any of my module's functions to be called before my hook_init(). Why have a hook called "init" if not to do whatever initialization my module needs before it's ready to do its work?
Comment #6
donquixote commentedReally? Where is this call to drupal_access_denied() defined?
Comment #7
salvisAh, yes, I was confused.
$page_callback_result = MENU_ACCESS_DENIED is set in (and returned from) menu_execute_active_handler(), due to $router_item['access'] being FALSE.
The end result is the same though: access is evaluated (and $router_item['access'] set) before hook_init() is called, i.e. the page request is doomed before the modules have been initialized.
Comment #8
donquixote commentedAnd after hook_init, the access callback would return a different result?
Comment #9
sunSee #553944-110: Define hook_menu_get_item_alter() as a reliable hook that runs before the page is doomed
Not sure whether this issue should be marked as duplicate or whether to move the problem into this issue. As of now, I think that keeping that other issue re-opened and resolving the problem there makes more sense.
Comment #10
salvisYes. hook_init() is the place to 'enhance' the $user object. After that, the access callbacks will evaluate differently.
Gotta run, I'll be back tomorrow...
Comment #11
webchickMarking as a duplicate. Let's figure this out over in the parent issue.