By greenbeans on
Hello,
I'm using the following code to hook a module into the menu system:
function metamenu_menu() {
$items['admin/settings/metamenu/path/%menu_tail'] = array(
'title' => 'Meta Menu Edit Path',
'description' => 'Assign flags to path',
'page callback' => 'drupal_get_form',
'page arguments' => array('metamenu_edit_path', 4),
'access arguments' => array('access administration pages'),
'type' => MENU_LOCAL_TASK,
);
return $items;
}
function metamenu_edit_path(&$form_state, $path) {
drupal_set_message($path);
...
}
Instead of the full menu tail, I'm getting just the first element of it -- e.g. if I visit "admin/settings/metamenu/path/foo/bar/baz", I only get "foo" output, instead of "foo/bar/baz", which is what I want.
I've googled the heck out of "menu_tail" and come up with nothing. Am I doing something wrong?
Thanks!
Comments
SOLVED
Never mind, figured it out. The callback function has to accept a variable number of arguments. The menu_tail is sent as a bunch of separate variables, rather than an array or a single string.
Same issue
I don't see how this is solved?
I'm seeing the same thing, and it's quite frustrating. menu_tail_to_arg() is being called, and it is generating the expected string ("foo/bar/baz" in the above example), but this value is not passed to the callback function. Which makes this useless?
As an example, the foobar() callback function below receives exactly the same arguments for both of the following paths:
foo/red/green/blue
bar/red/green/blue
So what is the point?
The only place %menu_tail is used in Drupal core is in search.module, but it looks like it is completely ignored. It uses search_get_keys() to figure out the search pattern instead.
Am I completely failing to understand this, or is this mechanism actually broken?
Following up my own query
Following up my own query, I see now that %menu_tail does serve an obvious purpose. As explained here, search_menu() uses it to generate local tasks with the full correct URL, if the search term contains a '/'.
But the problem still remains (to my mind) that %menu_tail is not then passed as a single argument to the page callback function.
As stated by greenbeans, as soon as you use it, your callback function has to parse func_get_args() and reconstruct the tail from there, which is unintuitive and seems inconsistent with the wildcard documentation.
If we create a menu_tail_load() function instead (but not with that exact name prefix, obviously) as a copy of menu_tail_to_arg(), and we add 'load arguments' => array('%map', '%index') to the menu item definition, then we can pass the tail to the callback, but we do not get the full tail in the menu item's URL.
There doesn't seem to be anything which does both, and I'm not seeing why the _to_arg() functions don't behave this way.
At the very least, there should be a clear note in the documentation along the lines of:
IMPORTANT: Unlike _load() functions, the return value of a _to_arg() function is NOT passed to the callback functions when you specify the arg number of the wildcard in your 'arguments' array. A _to_arg() function affects only the path of a menu item.
Note added
And I might as well do that myself :)
Note added here:
http://drupal.org/node/109153#to_arg
SOLVED :)
So in answer to my original question: Yes, I was completely failing to understand this.
Ironically, I explicitly ignored the solution in a previous reply:
In fact, that is exactly what you want to do.
After realising that the _to_arg() functions were purely about manipulating the path, and the _load() functions were purely about manipulating the callback arguments, and remembering that there were separate columns for each in the menu_router table, the penny finally dropped -- there's no conflict between these functions. You can implement both of them for a given wildcard prefix, and each will do their specific task.
Here's an example module based on the %menu_tail functionality.
I've also updated http://drupal.org/node/109153 more thoroughly, so hopefully this is much clearer now.