In a hierarchy of menu in admin/settings/mymodule made mainly by
MENU_NORMAL_ITEM, MENU_DEFAULT_LOCAL_TASK and MENU_LOCAL_TASK
I'd like that if anything deeper than:
admin/settings/mymodule
is rubbish it get a 404 or a redirect to admin/settings/mymodule
eg. admin/settings/mymodule/ashasha or admin/settings/mymodule/somefunction/jajasha -> 404
but I get: warning: array_merge() [function.array-merge]: Argument #1 is not an array in /*/includes/menu.inc on line 415. warning: Missing argument 1 for drupal_get_form() in /*/includes/form.inc on line 49. warning: Missing argument 1 for drupal_retrieve_form() in /*/includes/form.inc on line 179. warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, '' was given in /*/includes/form.inc on line 218.
hints?
Would need to see the menu $items definitions for these to give better feedback. It doesn't sound like you're generating the menu item correctly.
You should not be getting this message, but if you want a 404, you'll have to code that yourself in your callback. Something like:
if (!$_GET['q'] != 'admin/settings/mymodule') drupal_not_found();
The menu system passes this to your settings function by design.
Dave -----Original Message----- From: support-bounces@drupal.org [mailto:support-bounces@drupal.org] On Behalf Of Ivan Sergio Borgonovo Sent: Monday, January 28, 2008 7:14 AM To: support@drupal.org Subject: [support] 404 or alias for menu hook
In a hierarchy of menu in admin/settings/mymodule made mainly by
MENU_NORMAL_ITEM, MENU_DEFAULT_LOCAL_TASK and MENU_LOCAL_TASK
I'd like that if anything deeper than:
admin/settings/mymodule
is rubbish it get a 404 or a redirect to admin/settings/mymodule
eg. admin/settings/mymodule/ashasha or admin/settings/mymodule/somefunction/jajasha -> 404
but I get: warning: array_merge() [function.array-merge]: Argument #1 is not an array in /*/includes/menu.inc on line 415. warning: Missing argument 1 for drupal_get_form() in /*/includes/form.inc on line 49. warning: Missing argument 1 for drupal_retrieve_form() in /*/includes/form.inc on line 179. warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, '' was given in /*/includes/form.inc on line 218.
hints?
On Mon, 28 Jan 2008 08:01:14 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Would need to see the menu $items definitions for these to give better feedback. It doesn't sound like you're generating the menu item correctly.
mmm the menu works. I get the "root" menu in the admin page, the submenu in the navigation block and the tabs.
Menu hierarchy is something like:
$items[] = array( 'path' => 'admin/settings/mymodule', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings2', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action1', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings3', 'type' => MENU_DEFAULT_LOCAL_TASK,, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action2', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings4', 'type' => MENU_LOCAL_TASK, );
admin/settings/rubbish -> list of modules admin/settings/amodule/rubbish -> same page as admin/settings/amodule/ where amodule in (admin, fckeditor, localisation, uploads...)
But all those modules don't have submenu. So maybe it is something related to submenus (?)
Yes,
In drupal 4 & 5, the parent and default tab should generally have the same callback and arguments. My bet in the example that you gave in the last email is that the parent path's callback does not have a function defined that returns a form. Does that make sense?
That is admin/settings/mymodule/subsettings and admin/settings/mymodule/subsettings/action1 should look the same except for the menu type.
I know its redundant, but it's necessary.
Hopefully this makes sense, but if not, let me know what the tab user experience is you're looking for and I'll try and mock up an example.
Dave
-----Original Message----- From: support-bounces@drupal.org [mailto:support-bounces@drupal.org] On Behalf Of Ivan Sergio Borgonovo Sent: Monday, January 28, 2008 10:19 AM To: support@drupal.org Subject: Re: [support] 404 or alias for menu hook
On Mon, 28 Jan 2008 08:01:14 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Would need to see the menu $items definitions for these to give better feedback. It doesn't sound like you're generating the menu item correctly.
mmm the menu works. I get the "root" menu in the admin page, the submenu in the navigation block and the tabs.
Menu hierarchy is something like:
$items[] = array( 'path' => 'admin/settings/mymodule', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings2', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action1', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings3', 'type' => MENU_DEFAULT_LOCAL_TASK,, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action2', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings4', 'type' => MENU_LOCAL_TASK, );
admin/settings/rubbish -> list of modules admin/settings/amodule/rubbish -> same page as admin/settings/amodule/ where amodule in (admin, fckeditor, localisation, uploads...)
But all those modules don't have submenu. So maybe it is something related to submenus (?)
On Mon, 28 Jan 2008 11:24:17 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Yes,
In drupal 4 & 5, the parent and default tab should generally have the same callback and arguments. My bet in the example that you gave in the last email is that the parent path's callback does not have a function defined that returns a form. Does that make sense?
That is admin/settings/mymodule/subsettings and admin/settings/mymodule/subsettings/action1 should look the same except for the menu type.
I know its redundant, but it's necessary.
Hopefully this makes sense, but if not, let me know what the tab user experience is you're looking for and I'll try and mock up an example.
No, it doesn't make sense or I didn't understand.
That means that in a whole hierarchy of menu all have to call the same callback and then inside the callback function differentiate the calls?
That makes the menu system useful just to build up the menu layout (sort of).
Actually in Pro Drupal Dev. there are examples where the callback is different in submenus (but none in the admin interface that I could remember of) and examples where it is the same.
Just in the MENU_DEFAULT_LOCAL_ACTION the callback of the parent is not repeated, but my parents have a callback.
And yeah I did a mistake reporting the menu...
mymodule_admin_settings3 should actually be mymodule_admin_settings2 so that the MENU_DEFAULT_LOCAL_ACTION callback is the same as the parent.
So... actually my menu looks like:
$items[] = array( 'path' => 'admin/settings/mymodule', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action1', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action1', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action1', 'type' => MENU_DEFAULT_LOCAL_TASK,, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action2', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action2', 'type' => MENU_LOCAL_TASK, );
Even commenting out callback and callback arguments from MENU_DEFAULT_LOCAL_TASK still doesn't solve the problem.
Woops,
You've noticed that all of these are wrong:
'callback arguments' =>'mymodule_admin_settings',
They should all be:
'callback arguments' => array('mymodule_admin_settings'),
Also, remember to hit the administer menu page after each of these fixes, cause the structure is cached in the database. I noticed for example that your error message still references a function called drupal_retrieve_form which doesn't appear in your menu structure.
Dave
-----Original Message----- From: support-bounces@drupal.org [mailto:support-bounces@drupal.org] On Behalf Of Ivan Sergio Borgonovo Sent: Monday, January 28, 2008 12:03 PM To: support@drupal.org Subject: Re: [support] 404 or alias for menu hook
On Mon, 28 Jan 2008 11:24:17 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Yes,
In drupal 4 & 5, the parent and default tab should generally have the same callback and arguments. My bet in the example that you gave in the last email is that the parent path's callback does not have a function defined that returns a form. Does that make sense?
That is admin/settings/mymodule/subsettings and admin/settings/mymodule/subsettings/action1 should look the same except for the menu type.
I know its redundant, but it's necessary.
Hopefully this makes sense, but if not, let me know what the tab user experience is you're looking for and I'll try and mock up an example.
No, it doesn't make sense or I didn't understand.
That means that in a whole hierarchy of menu all have to call the same callback and then inside the callback function differentiate the calls?
That makes the menu system useful just to build up the menu layout (sort of).
Actually in Pro Drupal Dev. there are examples where the callback is different in submenus (but none in the admin interface that I could remember of) and examples where it is the same.
Just in the MENU_DEFAULT_LOCAL_ACTION the callback of the parent is not repeated, but my parents have a callback.
And yeah I did a mistake reporting the menu...
mymodule_admin_settings3 should actually be mymodule_admin_settings2 so that the MENU_DEFAULT_LOCAL_ACTION callback is the same as the parent.
So... actually my menu looks like:
$items[] = array( 'path' => 'admin/settings/mymodule', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_settings', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action1', 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action1', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action1', 'type' => MENU_DEFAULT_LOCAL_TASK,, ); $items[] = array( 'path' => 'admin/settings/mymodule/subsettings/action2', 'callback' => 'drupal_get_form', 'callback arguments' =>'mymodule_admin_action2', 'type' => MENU_LOCAL_TASK, );
Even commenting out callback and callback arguments from MENU_DEFAULT_LOCAL_TASK still doesn't solve the problem.
On Mon, 28 Jan 2008 12:11:28 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Woops,
You've noticed that all of these are wrong:
'callback arguments' =>'mymodule_admin_settings',
They should all be:
'callback arguments' => array('mymodule_admin_settings'),
That made it. I think I did a mistake somewhere and reported over and over and over... unfortunately the code is resilient enough to accept strings in spite of array most of the times.
drupal_retrieve_form was actually called down the path but without the correct number of arguments.
As for "making more sense"... I think it is time to sleep. Let me commit this working copy and later I'll see what happens if parent and default have different callback.
I think that different callback will make harder to navigate the menu/tab structure. Once you go to a tab it is hard to go back to the parent page. The Home > Administer > Site configuration > ... (how do you call it? It's a sort of breadcrumb...) at the top push you one level higher so you've to resort to the Navigation menu.
Avoiding duplication avoid duplicating correcting the code... so parent with callback and default with no call back make sense.
But "this is directly because of the behavior that you indicated you were trying to avoid :)" still does not.
Thank you very much... it was a minor annoyance (after all why users should test random urls? <evil grin> and it didn't look as a point of entrance for SQL injection... but I bet in a week or 2 it was going to eat me in some even more weird way ;)
-----Original Message----- From: support-bounces@drupal.org [mailto:support-bounces@drupal.org] On Behalf Of Ivan Sergio Borgonovo Sent: Monday, January 28, 2008 12:46 PM To: support@drupal.org Subject: Re: [support] 404 or alias for menu hook
Avoiding duplication avoid duplicating correcting the code... so parent with callback and default with no call back make sense.
But "this is directly because of the behavior that you indicated you were trying to avoid :)" still does not. --------------------------- Understood.... goodnight :)
For tomorrow :
Not until drupal 6 do menu callbacks get inherited. The menu is being routed to the right function in milkshake/list because milkshake/list is on the path for milkshake. If you put in milkshake/foo it should get processed by the same entry as milkshake, and if you registered your own function instead of drupal_get_form, say call it my_module_milkshake_overview() then that fuction would be called with a single parameter.
Consider the following in hook_menu
$items[] = array('path' => 'milkshake/list', 'callback' => 'mymodule_milkshake_list');
If you were to implement the function:
function mymodule_milkshake_list($type='') { // if the $type is specified then only list that type of milkshake. }
Now if you browse to milkshake/list/chocolate the function mymodule_milkshake will be called with $type containing a value of "chocolate". It is for this reason that the parents menu callback is always called when deciding what function to call.
Glad I could help....
Dave
-----Original Message----- From: support-bounces@drupal.org [mailto:support-bounces@drupal.org] On Behalf Of Ivan Sergio Borgonovo Sent: Monday, January 28, 2008 12:03 PM To: support@drupal.org Subject: Re: [support] 404 or alias for menu hook
On Mon, 28 Jan 2008 11:24:17 -0800 "Metzler, David" metzlerd@evergreen.edu wrote:
Yes,
No, it doesn't make sense or I didn't understand.
That means that in a whole hierarchy of menu all have to call the same callback and then inside the callback function differentiate the calls?
That makes the menu system useful just to build up the menu layout (sort of).
--- Yes you can have submenus with different callbacks, what I was really trying to get at was the tab specific case. See page 43 of the drupal dev book.
Notice that there is no callback for milkshake/list, but there is for milkshake. In effect the same callback gets used for the menu item for the MENU_CALLBACK item and the MENU_DEFAULT_LOCAL_TASK, this is directly because of the behavior that you indicated you were trying to avoid :). You could explicitly set the same callback for both items and get the same behavior.
Making more sense yet?