Consider a menu item 'something/%foo'. This indicates that the router will rely on foo_load to handle requests that match. foo_load is not guaranteed to exist, however. The current behavior when foo_load does not exist is for the {menu_router}:path to be set as 'something/%foo'. This will never match, however, because menu_get_ancestors only returns paths in their simplified form, ie something/%. Thus we are recording unmatchable paths into the {menu_router}. The correct behavior when foo_load is missing is to not build that item and not record it to {menu_router} because it can't be served, due to the missing load (or _too_arg) function. Here's the patch:
diff -u -p -r1.255.2.16 menu.inc
--- includes/menu.inc 25 Jun 2008 08:49:25 -0000 1.255.2.16
+++ includes/menu.inc 2 Jul 2008 19:36:35 -0000
@@ -2218,6 +2218,7 @@ function _menu_router_build($callbacks)
$match = TRUE;
}
}
+ if (!$match) { continue 2; }
}
if ($match) {
$parts[$k] = '%';
Comments
Comment #1
pwolanin commentedneeds a code comment - and maybe a test :)
Comment #2
robertdouglass commentedI've confirmed the bug exists in HEAD as well, so here's a commented patch and a test.
Comment #3
robertdouglass commentedMissed a couple of details.
Comment #4
pwolanin commentedThis looks like the queries are not correct?
should maybe be:
note: %%
Comment #5
robertdouglass commentedYes, that's right. Thank you.
Comment #6
robertdouglass commentedFeedback from chx:
- code style (newlines after and before {} )
- move continue one line up so that foo/%/bar doesn't get mangled
- add foo/%/bar to the test.
Comment #7
robertdouglass commentedWhile it wasn't true that the 'foo/%/bar' path breaks with the proposed change I moved the !$match test up a line anyway. This makes it a more targeted case that only cares whether a _to_arg or _load function is missing. Code style corrected and 'foo/%/bar' test added.
Comment #8
pwolanin commentedcode looks fine, test works. Not an urgent bug, but useful to fix for developers.
Comment #9
robertdouglass commentedSo, RTBC?
Comment #10
dries commentedI think this looks like a good fix. I'm wondering though, whether it is in our interest to 'fail silently'. Wouldn't it be better to generate a warning or error message and to correct the developer?
Comment #11
damien tournoud commentedDoes that mean that we don't care to support path elements that start with a '%'?
Is it possible in the current implementation?
Comment #12
robertdouglass commented@Damien Tournoud: Nothing in the API is changing with this patch. '%' paths are still supported as before. We were 'failing silently' while polluting the database before. Now we're failing silently without polluting the database. I'll roll another patch that adds a watchdog message.
Comment #13
robertdouglass commentedQuestion with regards to #10: if I put a watchdog message in menu.inc, is there ever a bootstrap situation where menu.inc gets loaded but watchdog isn't available? I'll look into this, too. Are there any other reasons for or against failing silently?
Comment #14
damien tournoud commented@robertDouglass: sorry, I wasn't clear enough. I was talking about paths that would actually have a "%" in them. For example:
mymodule/%C3%A0-la-claire-fontaine(that's the encoding of "à la claire fontaine"). Do we support them today?Comment #15
pwolanin commented@Damien - no, those are not supported today - at least not as actual paths. The arguments (trailing parts) can have any characters.
Comment #16
pwolanin commentedI don't think we need a watchdog message - you would really only have these failures while developing a module.
I think the existing patch is fine - if we really want to give developers more info, perhaps we could use a flag like is done in _db_query:
Though per Barry's DX post, we should think about having a define that we could perhaps use a few places:
Comment #17
robertdouglass commentedHonestly, I'm fine without any failure warning. There are probably hundreds of places where we could insert
if (DEBUG) somethingin all of Drupal. It seems arbitrary to start here.Comment #18
chx commentedOpsie. Isn't this the usual "we do not babysit broken code"? This will be in the memory of every Drupal site out there and fire never unless you have written broken code but then you deserve a broken site.