Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
This just can't be done. Use a custom access callback and be done.
Comment | File | Size | Author |
---|---|---|---|
#23 | menu_78.patch | 29.7 KB | chx |
#22 | menu_77.patch | 29.48 KB | chx |
#17 | menu_76.patch | 21.45 KB | Steven |
#16 | menu_75.patch | 20.68 KB | Steven |
#14 | menu_74.patch | 18.33 KB | chx |
Comments
Comment #1
webchicksub
Comment #2
Nick Lewis CreditAttribution: Nick Lewis commentedTotally agree -- in my experience this is one menu constant that needs excessive massaging to get to work (still haven't had the patience to figure out exactly why my attempts sometimes go wrong...), and the default results are usually so insufficient that I've always ended up writing my own callback to process the menu tree anyway.
To put it another way, where have you see 'type' = MENU_ITEM_GROUPING outside of the drupal core? Can't think of any examples off the top of my head :-).
Given the importance of the menu system, and its current lack-of-intuitiveness, (and my personal observation that it is always a huge stumbling block for developers new to drupal) any change that simplifies it is a good thing in my book.*
*but don't make it too simple, of course.
Comment #3
bdragon CreditAttribution: bdragon commentedMy impressions:
Good:
1) The first menu item at every level is now appearing again. (My Account, Page, Site Configuration, etc..)
2) The aggregrator isn't dumping stuff in the root of its submenu anymore.
Questionable:
1)
Can we have a db_table_is_empty() function? It took me a second to figure out what the intention was here, and it looks like a useful predicate (Yeah, I know, another issue..)
Bad:
Couldn't find anything bad, sorry ;)
Misc:
1) The local tasks weren't being highlighted at first. After enabling some modules, it started working again, so I assume it was a caching problem.
2) Could someone with a full contrib checkout or grep access do a tally for MENU_ITEM_GROUPING?
Overall:
Lookin' good.
Comment #4
bdragon CreditAttribution: bdragon commentedAnd 5 seconds after posting:
The code I had marked as "Questionable" really is so. You meant db_query_range() there, not db_query(), correct?
Comment #5
chx CreditAttribution: chx commentedYes I meant db_query_range. No, I do not see the point in abstracting such a trivial query.
Comment #6
chx CreditAttribution: chx commentedThe more, the merrier!
l()
I added all the thingsl()
supports to the database, query fragment etc etc. This includes aliased path storage.Comment #7
chx CreditAttribution: chx commentedProper alias storage: separate from path, synced from path_set_alias.
Comment #8
chx CreditAttribution: chx commentedpath_set_alias makes my head hurt. What about simplifying and commenting that beast? It will result in less and more easily understandable code and a nice place to tuck the menu update query in.
Comment #9
eaton CreditAttribution: eaton commentedTested and approved. Adding, deleting, editing, and generally folding and spindling paths works nicely. Setting multiple aliases for the same path works, too. Hoorah.
I've removed a spurious menu_rebuild() removed from index.php, but other than that it's the same patch that chx posted. I'm setting RTBC.
Comment #10
Steven CreditAttribution: Steven commentedThere was a big fuss over whether bubbling should be allowed. There are various interpretations of this: one is simply whether we should show accessible deep items in the navigation block at the top level or not. Another is whether it makes sense that you can access "admin/build/block" when you can't access "admin" or "admin/build".
My impression was that the result of that discussion was that we should not show these links and not allow access either.
However, this is not at all what the current patch implements. Old items that would bubble are not visible in the menu, unless you type their path directly. IMO this is unacceptable as pages that appear to be inaccessible are really not.
If you go to such a 'deep' page, the link appears in the menu, but is indented, though at an incorrect level. Try giving e.g. anonymous users the "administer blocks" permission. I don't think this is intentional behaviour, looking at the code:
menu_tree() fetches a flat list of all menu items, in the order they appear in the (fully expanded) tree. _menu_tree() then runs through it, recursing at the appropriate steps.
If the user has access to the entire tree, the code will correctly recurse through and output the nested lists.
However, if a user does not have access to a particular item with children, the while () iteration will be aborted with
continue
. However, all those db_fetch_object() calls for the children that would've been called in the recursive call to _menu_tree() have not been done. So, the next while () iteration will in fact fetch the first child of the disallowed menu item, check its access, and output it. And because the recursion was not performed, the code will stop prematurely at the end of the submenu and come one recursion short.Obviously we could address this bug by patching _menu_tree(), but that still wouldn't solve the problem that permissions appear to be hierarchical while really being flat. This could pose security issues.
IMO we should move to complete hierarchical permissions and perform access checking up the tree for each page. It's the only consistent solution to the bubbling problem. It could allow us to simplify the access callback inheritance rules though.
I'm also not 100% sure about dropping MENU_ITEM_GROUPING. It is a useful feature... access callbacks only work if the module that owns the item knows exactly what items are under it. This is true for e.g. create content, but not for the admin pages. Without such functionality, we'll be doomed to useless permissions such as "access administration pages", no?
While it is relatively easy to implement in the current model (just add a snippet in _menu_translate to do the right query and checks), the problem is that we'd have to recurse up the entire top-level admin tree (down to each
admin/foo/bar
) to determine the visibility, which would probably kill performance.Comment #11
chx CreditAttribution: chx commentedI will add more comments to _menu_tree , sure. To match the navigation tree behaviour, when you land on a page, we will access check every parent too and
AND
them together. As this happens once (instead of iterating in the menu tree), there is very little performance penalty and little complexity added. mright is currently not used, but it's very useful, you can pick all the children of a menu item if you want to with one query. Permissions for administer pages are forthcoming as discussed on devel. Theming is easy to change, too.Comment #12
chx CreditAttribution: chx commentedExecuted the battle plan I checked with UnConeD. It dawned on me that the items we access check in menu_get_item now are the active trail. So I put that to good use: breadcrumbs are back.
Comment #13
chx CreditAttribution: chx commentedDang, I forgot my menu_rebuild in again.
Comment #14
chx CreditAttribution: chx commentedThis time, the correct patch :(
Comment #15
Steven CreditAttribution: Steven commentedThe patch looks great (much more understandable now), but I have one more thing to add... now that access lookups are performed up the tree, we no longer need to inherit access callbacks for the case where the arguments do not change. This should save some useless duplicate access checks. :)
Comment #16
Steven CreditAttribution: Steven commentedImplemented the above. In the case where we would inherit an identical access check, we set the callback to TRUE instead.
Comment #17
Steven CreditAttribution: Steven commentedFixed some more problems:
Comment #18
Dries CreditAttribution: Dries commentedWouldn't it be cleaner to replace
db_num_rows(db_query_range('SELECT 1 FROM {aggregator_category}', 0, 1)
withdb_result(db_result('SELECT COUNT(cid) FROM {aggregator_category}'))
or isn't that what this line does?What is
block_callback
for? It does not appear to be used?Some of the code comments (i.e.
+ // New alias.
) add no value.Some of the code comments are a little bit cryptic. What does 'inherited normally' means, for example? Why can't we inherit from certain menu items? The code comments explain what the code does, but often not _why_ it does that. While the code comments got better, they are far from great.
That said, great job Steven and chx. :)
Comment #19
chx CreditAttribution: chx commentedWe are not interested in COUNTing all aggregator categories, I am just interested in whether there is at least one item in the table. I believe selecting one element is faster than the count for the whole table. block_callback is for the forthcoming admin pages.
Inheritance, my example was that if A(ac, aa), B(), C(,aa1) where ac is access callback, aa/aa1 is access arguments, then B.ac becomes TRUE but that's just an optimization, C.ac needs to be A.ac.
Comment #20
Crell CreditAttribution: Crell commentedThe speed trade-off is database-dependent. In MySQL/MyISAM, if you just want to know "how many rows" there are (or "is there at least one row") then
count(*)
is already extra-indexed to be virtually instantaneous. I don't believe that's the case in MySQL/InnoDB or Postgresql, but I am not an expert in those databases.Queue stock line: Benchmarks would be good to see which method is faster, when.
Comment #21
chx CreditAttribution: chx commentedI am pretty sure the difference is way too small to be benchmarkable or significant. If the database is on the same machine, it's likely instant, if it's on another machine, you need a query, which in itself takes very little time and the network travel is the battleneck. Let's not barb into this, OK? If Dries asks me, I will change the query, if not, I will let it be.
Comment #22
chx CreditAttribution: chx commentedFixed aliasing logic glitches in _menu_translate and moved everything into the function so the return value is much simpler now, and so are everything related _menu_translate . Further simplified path_set_alias logic. Most admin pages are back -- by module is not yet. Improved inheritance comments.
Comment #23
chx CreditAttribution: chx commentedQuery changed, comments clarified.
Comment #24
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. It's not perfect, but it's another great milestone. Further improvements and fixes can go in follow-up patches. Thanks!
Comment #25
(not verified) CreditAttribution: commented