Menu.in and menu.module need to support multiple menus. Here's Karoly's call to battle on the devel list:

The way I imagine this.

a) hook_menus to define multiple menus.
b) menu_menus table to store 'em. (of course, hook_menu has an FK to this)
c) menu_rebuild gets renamed to _menu_rebuild and gets the menu name as
argument
d) hook_menu also gets the name of menu as argument, returns the menu
items in that menu.

CommentFileSizeAuthor
#125 system-menu-router-links.patch1.92 KBbjaspan
#122 p6_menus_17.patch78.13 KBchx
#120 p6_menus_16.patch79.75 KBCrell
#111 p6_menus_15.patch78.1 KBandremolnar
#110 p6_menus_14.patch78.17 KBchx
#109 p6_menus_13.patch79.21 KBpwolanin
#104 p6_menus_12.patch75.61 KBchx
#98 p6_menus_11.patch75.58 KBchx
#92 p6_menus_10.patch75.26 KBpwolanin
#88 p6_menus_9.patch74.86 KBpwolanin
#87 p6_menus_8.patch73.28 KBchx
#86 menu_inc_changes.txt7.19 KBpwolanin
#85 p6_menus_7.patch74.98 KBpwolanin
#79 p6_menus_6.patch71.94 KBchx
#67 p6_menus_3.patch70.09 KBchx
#63 menu1_1.png29.61 KBchx
#62 p6_menus_0.patch68.5 KBchx
#61 p6_menus_5.patch75.18 KBpwolanin
#60 p6_menus_4.patch68.24 KBpwolanin
#59 p6_menus.patch66.75 KBchx
#58 menu1_0.png14.16 KBchx
#57 p6_menus_2.patch67.88 KBpwolanin
#49 p6_menus_1.patch59.05 KBpwolanin
#48 multiple_menus_8.patch59.1 KBchx
#47 multiple_menus_12.patch59.13 KBpwolanin
#40 multiple_menus_2.patch58.38 KBchx
#39 multiple_menus_1.patch58.77 KBchx
#38 multiple_menus_10.patch54.88 KBpwolanin
#35 multiple_menus_0.patch54.7 KBchx
#33 multiple_menus_7.patch54.04 KBpwolanin
#32 multiple_menus_6.patch53.88 KBpwolanin
#31 multiple_menus.patch52.11 KBchx
#30 multiple_menus_5.patch53.09 KBpwolanin
#29 multiple_menus_4.patch52.69 KBpwolanin
#26 multiple_menus_3.patch49.02 KBpwolanin
#24 separate_menu_tables_9.patch40.7 KBpwolanin
#20 separate_menu_tables_8.patch44.86 KBpwolanin
#14 separate_menu_tables_6.patch40.25 KBpwolanin
#10 separate_menu_tables_5.patch39.49 KBpwolanin
#9 separate_menu_tables_4.patch35.33 KBpwolanin
#6 separate_menu_tables_3.patch26.29 KBpwolanin
#5 separate_menu_tables_2.patch15.56 KBpwolanin
#3 separate_menu_tables_1.patch9.89 KBpwolanin
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

chx’s picture

Thanks for taking this issue. We discussed here a bit. Two challenges: menu module needs to edit menus defined by other modules. And menu titles are highly dynamic, the navigation block is titled check_plain($user->name)

pwolanin’s picture

Ok, I'm getting a bit stuck moving forward- here's why: Right now, the path is the primary key of the {menu} table, and thus a single path can only exist once. With multiple menus, each path can appear once (or more than once?) per menu. The path is also the key of the array that is build from calling hook_menu, and thus mus be unique in this context as well.

This is what I 'm thinking now- we need an additional table- something like {menu_display}. This would be keyed by menu name as well as path, and would contain all custom menu items and external links. This would map directly to the contents of blocks. In this way, I think the 2 calls to drupal_alter() will be for 2 different data structures:

1st call will allow modules to work on the {menu} to alter the callbacks or access parameters of module-defined paths.

2nd call will be for the {menu_display} data to allow addition of external links, links to individual nodes, links to individual users, etc.

As I imagine it, this split will also minimize the siz of the {menu} table, which should have some performance benefits even if there are links to 10,000 individual nodes being displayed via menus in blocks.

Since I'm still getting my head around the full 6.x menu system as Karoly coded it, I'd appreciate feedback on this direction.

pwolanin’s picture

Status: Active » Needs work
FileSize
9.89 KB

ok, so things are very broken with this patch, but it's a first step to separating into two tables.

chx’s picture

Two tables, yes, sure. In the beginning I was even contemplating (and mailing devel) about splitting the hooks into hook_router and hook_menu but later realized that's not necessary or good so I contemplated two tables which indeed became necessary. Rock on.

pwolanin’s picture

FileSize
15.56 KB

don't try to actually use this patch- it's very much a snapshot of work-in-progress. I'm trying to separate all the code that builds the {menu} table from the later code to build the {menu_links}

pwolanin’s picture

FileSize
26.29 KB

Hey, this patch code is getting somewhere towards functional in terms of separating the callbacks from the links.

I think it actually simplifies the logic quite a bit in places. I'm also trying to break up the monster menu_rebuild() into several functions.

For saving menu items, is it kosher to save (for example) 100 at a time in a big query string? Similar to what you get by running mysqldump?

Crell’s picture

You mean like this?

INSERT INTO foo (a, b) VALUES (1, 2), VALUES (3, 4), VALUES (5, 6);

That's MySQL-specific, so no, that's no good. Some other database engines allow multiple full INSERT statements in one query command, but MySQL does not for injection-prevention purposes. Just stick with one query call per insert.

menu_rebuild() is, hopefully, a rarely called function so its performance is not super-critical.

pwolanin’s picture

Ok, thanks- I won't try it then. In any case, the functionality needs to preceed optimization to some degree.

pwolanin’s picture

FileSize
35.33 KB

well, I may have bolluxed as many things as are fixed (especially _menu_translate() and perhaps my misunderstanding of the to_arg functions), but I think this is moving closer to a logical separation of menu callbacks and menu links.

pwolanin’s picture

FileSize
39.49 KB

Ok, the last set of changes broke some of the menu tree code somehow, but anyhow I think it represents progress:

1) fixed code in user_current_to_arg()

2) made it so system module declares a set of menus for all items like admin/X

3) Put all the menu items like admin/X/Y into the admin/X menu (i.e. all the by-task items)

4) change the system block code to use menu_tree() rather than a direct query, so The admin page kind of works again.

So this now demonstrates (more or less) how to build multiple menus with the new code and tables. Note the menus described by #2 have 'customizable' == FALSE, with the idea being when the menu module itself it brought into alignment with these changes, it will not list these admin menus as ones where you can add/disable items.

pwolanin’s picture

quick list of obvious bugs:

1) Menus are not expanding

2) When you are on a page corresponding to a local task, the tabs disappear.

3) No support yet for a by-module admin overview. This is a little trickier. Maybe menu module needs to do a customized module_invoke_all so that the name of the declaring module can be stored with each menu callback?

quick list of things to change:

1) menu_tree should return a non-rendered data structure and a separate rendering function needs to be built- this way the book module, for example, could use the tree information to build the book navigation.

2) The per-user menu_tree data structures, and other menu info should be cached (eventually).

chx’s picture

user_current_to_arg is designed to always return the current user id. That's how my account link works even on user/564854 pages. _menu_check_access does not make any sense to, i surely miss something. I do not readily get what are you doing with admin/*, even if we decide it's a good idea, it's a separate patch, but while yes, it is similar to menu tree, the descriptions make it distinctive.

Otherwise, it's a fantastic piece of effort. Thank you really much.

Changing menu_tree to return a structure -- I do not like the idea, book/outline module can easily reuse the menu table itself, it's trivial to write a query which gets the items in menu order.

pwolanin’s picture

@chx - here's one reason why I think have the structured data is important- it's not just one query to build this. This menu can include links to lots of nodes, so for every node in the menu you also have to do a node_access() check before deciding whether it will show up in the menu or in the navigation. For the sake of efficiency, I think it's really important to have each menu tree cached per user (or, at the very least, saved in a static variable), which means calculating only once all the access checks per user.

As far as the user_current_to_arg()- I don't really think we want what you are suggesting. If so, zillions of links on d.o will get broken, right? Also, this is quite confusing, since if it works the way you suggest, if you go to URL user/999999 you'll still see this as the address, but see your own account page.

pwolanin’s picture

FileSize
40.25 KB

@chx - I think I'm a little confused by the dynamic wildcard replacement you originally envisioned: http://drupal.org/node/109153

Is the dynamic (to_arg) replacement only doe when rendering links, or should it also happen when handling a request?

I you original menu.inc code, it's the former, but reading the handbook page linked above it seemed to imply (to me) that to_arg worked in both cases.

chx’s picture

Let's make the menu_tree structure a separate issue, OK? I was also thinking of somewhat doing array-ish things in there. Let's dissect _menu_translate on a MENU_HANDLE_REQUEST . First of all, $path_map becomes map which is the exploded stuff of the current path. Second, to_arg_function is not called at all, there is a if ($operation == MENU_RENDER_LINK) which stops that. It's the object loading calls that happen all the time because the access checks needs those. I am sorry if the menu handbook is confusing, I will look at it. I do not readily see what gets broken, I tested that if I am user 1 and go to user/2/edit then my account still points to user/1 and all the tabs point to user/2. This was some time ago, but I believe it still stands.

This all can be cleaned up, lots after or during this patch because we longer need to mesh the user/%user router item with the user/_actual_user_id_ menu link. Yay.

pwolanin’s picture

@chx - a quick thought here, more later:

I was thinking about this a lot last night, and realized that even in the case of a menu with a few nodes showing (e.g. 10), the current rendering system is going to be deadly for performance, and doubly so if there is an access control module. The way it's set now, a full node_load() followed by node_Access() will need done to check the access status of each node link! So, I think we need to generate the data structure/array containing the links, then special-case nodes and use a query with db_rewrite_sql to find out which of the nodes the current user is allowed to view.

add1sun’s picture

subscribing

chx’s picture

I can see your problem but first can we get the split storage and the multiple menus working and more on later issues? We need to support multiple menus in menu.module , too... optimization can come later -- not just can, it needs to, but first let's get this one out of the door.

pwolanin’s picture

Yes, I agree that we need function before optimization, but I want to get all these issues on the table so it informs our thinking about which functions to split and possible

pwolanin’s picture

FileSize
44.86 KB

getting much better, but not quite perfect. Tabs seem to work (mostly) after some servious revamping of function menu_local_tasks().

Note- no PostgreSQL schema yet, and the changes to system.module should be a separate patch eventually.

Gábor Hojtsy’s picture

pwolanin asked me to come and help out get this patch in line with the latest menu localization changes, but as it seems from his latest patch, the title and description translation code is already there, so I don't see what is the supposed conflict or problem with menu localization?!

Gábor Hojtsy’s picture

Oh, I got an email from pwolanin, which I will repeat here, so it is saved for history.

Hi,

pwolanin wrote:
> regarding this patch: http://drupal.org/node/128082
>
> I'm trying to figure out how to merge it in with multiple menu patch I've
> been working on with advice from Karoly: http://drupal.org/node/137767
>
> In particular, which the new locale system should t() be called with
> user-entered text. For example, when the user enters a link and the text
> for the link, should t() be called on that as well as on the title? I
> guess a roughly equal question is whether t() now gets called on node
> titles?
>
>> From this: http://api.drupal.org/api/HEAD/function/node_page_view
> It doesn't seem to be the case.

The new menu localization system makes no difference between built-in menu items and user defined menu items, when it comes to localization. This is because we have no solution yet to translate user defined interface elements, but are in the works with one. If Drupal 6 will not include a user defined interface translation solution, we can still pull the plug on t()-ing user defined text, until that this is an accepted wrong way.

I am equally fine with checking for custom vs. built-in menu items, and only translate built in ones for now. Then put a TODO note into the comment in the "else" branch of the code, that there comes the user defined translation :)

We are still working out performance issues with user defined text translation (otherwise our model is very simple and works nicely). I hope we will have it done in time for Drupal 6.

Gabor

pwolanin’s picture

Tehre is no conflict, I was just trying to understand what that recent patch did so I could incorporate it.

As you say, we should probably add translation at least for the cases where the menu_link's link tet is identical to the module-defined menu title.

pwolanin’s picture

Here's the essential core of the patch, excluding proposed changes to system.module's building of the admin page. With just this, the admin page is broken again.

@chx - thinking about our conversation. Is it really not feasable to build the links in memory? I think it could be if we go back to your idea of doing hook_menu_links_alter one named menu at a time. Then even for a big site like d.o, we're not imagining building all the book pages at once, but only 10-20% of them. Maybe ~2-3 MB of memory? I'm just imagining that trying to build the re-build that part of the table by doing 2000 inserts is going to be worse, and the numbering, finding parents, re-parenting, etc seems a lot easier.

pwolanin’s picture

@chx- ignore most of the previous comment- obviously I didn't get enough sleep since in either case we're doing the same number of DB inserts.

pwolanin’s picture

FileSize
49.02 KB

attached patch includes work Karoly has done in the last couple days. My contribution to this today is to get the rendering of the navigation menu working. If you look at the patch, there is now a function that returns the *data* corresponding to the menu links tree that is currently being rendered This is with the idea that other modules (e.g. the follow-on to book.module) can use this data to render navigation elements, or that we can use it to render the breadcrumb trail, etc. without doing any additional queries (a static variable is used to cache the result- in the future we can actually use the cache system).

chx’s picture

Ooooooh! You figured how to do the data collection-HTML separately? My brain exploded when I tried. How very nice. We will be able to reuse that in so many ways. Thanks!

pwolanin’s picture

@chx - the data collection was 90% there in your patch, so I just carried it over the finish line.

pwolanin’s picture

FileSize
52.69 KB

I'm trying to fix the problems with local tasks in the previous patches(they really are not working now below level == 0). I think the real fix involves another change to the {menu} table.

Right now, the number stored in tab_depth is always the same as num_parts, so we really don't need it. What we need instead is the
tab_root, as well as the tab_parent. The tab_root will be the path of the non-tab below which a group of tabs belongs, while tab_parent will be the path of the router item that's the parent of a given tab. Thus, tab_parent will be empty for a non-tab page.

Attached patch implements this (after much angst). This allows us to get and present all the tabs for unlimited levels using a single query.

pwolanin’s picture

FileSize
53.09 KB

minor additional changes to function menu_tree_data() to move towards proper handling of links vs. router items.

chx’s picture

FileSize
52.11 KB

Awesome! This version removes an empty Navigation block, and fixes system_admin_menu_block .

pwolanin’s picture

FileSize
53.88 KB

Just an update of chx's last patch to accomodate this commit to HEAD: http://drupal.org/node/137211

pwolanin’s picture

FileSize
54.04 KB

minor additional work to start to get breadcrumbs working again. Not quite there yet for local tasks (it's some problem building up the menu tree)

pwolanin’s picture

To simplify the rebuilding process, I'm wondering if we should only allow router item links to be added to the 'navigation' menu?

That would also probably mean we could do away with menu_get_names() and hook_menu_info(), or at the least simplify menu_get_names() by making it a query to find the unique menu_name entries in the {menu_links} table. Then, a module could make a new "menu" just by inserting one or more links with a new menu_name into {menu_links}. Menu module can then just keep a list of its own menu_name entries, and only offer to customize those (plus 'navigation').

Note that's I've started trying to let modules set a "context" for their breadcrumbs, etc with functions menu_get_active_menu_name() and menu_set_active_menu_name().

I'm imagining that this could be used by a module like book module to make the visible breadcrumb easily match the menu hierarchy.

chx’s picture

FileSize
54.7 KB

Another round of patch. This one introduces the oh-so-important menu_link_save API function. The feature set is at such a point that now I would like to see this one fixed, ironed out (like writing an UPDATE statement), etc. and later, in separate patches menu.module and book.module can use that menu_link_save . I have a text that explains the maths involved.

pwolanin’s picture

can you post the math page as a new page in the 6.x menu handbook and link from here?

pwolanin’s picture

@chx - pasted in your description of the new system here: http://drupal.org/node/141866

pwolanin’s picture

FileSize
54.88 KB

@chx - this is a bit of cleanup as we discussed.

To make life simpler, router items will only be added to the 'navigation' menu. Thus, it seems pretty safe to just delete all items from {menu_links} with this menu_name and start fresh. Adds a new hook hook_navigation_links() which is called when the navigation menu is rebuilt. Removes hook_menu_info(), since this is something menu module itself should handle.

Added a call to drupal_alter('menu_link', $item, $menu) in function menu_link_save().

Also, got menu_get_active_trail() working better for local tasks, so breadcrumbs and title work better.

chx’s picture

Status: Needs work » Needs review
FileSize
58.77 KB

I am not so sure our work is so much easier if we restrict router items to the navigation menu. You can't delete everything from there the same as you can't delete any other menu. So I have removed this. However, with tasks, breadcrumb, title and navigation menu all working I am deeming this ready to review. Menu module supports come later. I added a module column to menu_links so that for example menu module does not start to customize book module links...

I am very happy how our duo was working on this big, big rehaul. It's good to have another man on board -- it makes our code even better. Instead of cleaning up in Drupal 7, Peter cleaned up (and/or forced me to clean up) the code. Fantastic!

There is still work to do in other patches:

  1. menu module needs to completed
  2. Book module now can use menu!
  3. update path needs to be written
  4. we still need permissions that let you reach the various admin pages but nothing else, because of the loss of the bubbling effect
  5. the access checking needs to be deferred after _menu_tree_data so that becomes cacheable
chx’s picture

FileSize
58.38 KB

Another action point: we need to check all menu_rebuild calls in core and remove them in favor of menu_link_save calls.

pwolanin’s picture

Status: Needs review » Needs work

@chx- haven't looked at this patch in detail, but per my e-mail I think the table architecture needs to be refined further to enable efficient re-parenting for menus with a large number of items. Per my e-mail, I think we can do this by breaking out the "parents" column into 5 or 6 separate int columns if we are not constrained by having to get the items at a given depth in the right order as they come from the DB.

chx’s picture

Status: Needs work » Needs review

There is time for refinement later.

pwolanin’s picture

Ok- what about the navigation menu? I still think we're going to have trouble doing a menu rebuild if router items can be declared as going into menus other than navigation. Assume the module that did this is disabled- there is no way now to find the "dead" menu links unless you've stored somewhere all the router items from the last time you did a menu rebuild, right? Actually - this might be the best approach, since then you could disable or delete all menu_links that use a router item that has been removed from {menu}.

The way I coded it in my last patch I'm imagining that menu module (for example) could use the hook_menu_link_alter to change the menu a router item is saved to, but also keep track of this so it can do a cleanup if the router item gets disabled.

chx’s picture

  $placeholders = implode(', ', array_fill(0, count($menu), "'%s'"));
  // Remove those items which router path does not exist any more.
  db_query('DELETE FROM {menu_links} WHERE router_path NOT IN ('. $placeholders .')', array_keys($menu));

What's your problem?

pwolanin’s picture

No problem- that code will work. But, how will performance be with ~300 keys and 10,000 links? Would it be more to get all the existing paths from {menu} before truncating it? In that way, you can check if any of the existing paths are missing after the rebuild and write the query as IN() rather than NOT IN().

pwolanin’s picture

Status: Needs review » Needs work

missing a DB column "system" in {menu_links}

pwolanin’s picture

Status: Needs work » Needs review
FileSize
59.13 KB

Ok- the columns 'system' was there, but the insert/update code wasn't quite right in function menu_link_save().
Also made a minor change to the query (use COUNT(*) instead of db_num_rows()).

Additional small change to menu_set_active_trail()- link to 'Home' is added there instead of in get_breadcrumb. That way, BC can be full changed to cut off 'Home' link.

Updated patch attached.

chx’s picture

FileSize
59.1 KB

It was deliberate to leave out the module column from update -- you never want to update that.

pwolanin’s picture

FileSize
59.05 KB

Ok, per my e-mail to Karoly, here's a totally different way of constructing the menu order- the parents (each element of the materialized path) each have their own int column- up to 6 deep. I think this makes the code much simpler. The re-parenting isn't implemented yet, but all other functionality seems ok. If there is some reason to have menus deeper than 6 levels, this can easily done by adding additional columns- please comment!

I've added a description of the method form my e-mail here: http://drupal.org/node/141866#materialized
I think that especially for re-parenting this method is a big winner since all the work can be done in 2 queries regardless of the number of elements in the menu tree.

chx’s picture

I like Peter's method. It's indeed a clever trick using the fact that we know the max depth of our tree.

webchick’s picture

When enabling menu.module, you get:

Fatal error: Call to undefined function _menu_primary_links() in /Applications/MAMP/htdocs/head/includes/menu.inc on line 734

I was told by chx not to enable menu module, but since this is added by this patch, it probably should have a stub function or something as a safety.

Also, there is no update path. chx tells me that that will be added after this patch is committed.

When I enabled 'create book' permissions for authenticated users, neither "Create content" nor "Create book page" appears.

I clicked around to a bunch of stuff and it otherwise appeared to be in order, but I wasn't able to give it my total full attention so probably needs another set of eyes.

pwolanin’s picture

Clearly this is not yet RTBC- the basic question at this point is whether menus, tabs, breadcrumbs, etc. work and whether you have opinions on the algorithms being employed in the code.

This current work lays the infrastructure for menu.module, book.module, etc. (but they should all be optional for a site that wants just a simple navigation menu). Obviously the final patch will include an updated menu module, upgrade path, etc. I'll re-roll tonight with a stub for menu module to avoid reviewer confusion ;-)

chx’s picture

I believe that if you can get

When I enabled 'create book' permissions for authenticated users, neither "Create content" nor "Create book page" appears.

this one fixed, then it is good to go -- we have the backend in place, let's get it moving.

pwolanin’s picture

Priority: Normal » Critical

@chx - any ideas on this problem? node_type_form_submit() calls menu_rebuild() already. Appropriately, since additional callbacks may be created or removed.

Some other outstanding concerns that need to be resolved:

  1. Should the code that deletes links if their callbacks are gone also try to re-parent any orphaned children? Or maybe these links should be disabled rather than deleted?
  2. re-parenting needs to be implemented and tested.
  3. some of the admin/log/X items end up in the {menu} table with access_callback == 0
  4. The active trail includes the current page, so the last item in the breadcrumb is the current, rather than parent, page.
  5. should the allowed depth be > 6?
  6. Are the table indices working? We need to generate a reasonably large {menu_links} table to test it.
  7. When inserting a new menu item, do we need to check that the parent has depth < 6?
  8. When re-parenting, do we need to check that neither that item or any of its children will have depth > 6? What should the code do in this case?
chx’s picture

Should the code that deletes links if their callbacks are gone also try to re-parent any orphaned children? Or maybe these links should be disabled rather than deleted?

This falls into not babysitting broken stuff. But then again, a user might just move his / her stuff in there. Disabling won't work, we do not bubble, reparenting can be much, much work... let's give this more thought. Maybe anoher issue.

re-parenting needs to be implemented and tested.

Definitely a whole another issue. I believe the next two issues, in parallel are upgrade path and reparenting.

some of the admin/log/X items end up in the {menu} table with access_callback == 0

I believe some admin log paths are botched, there was already an issue for them. Please look at this.

The active trail includes the current page, so the last item in the breadcrumb is the current, rather than parent, page.

That's easy to fix...

should the allowed depth be > 6?

No.

Are the table indices working? We need to generate a reasonably large {menu_links} table to test it.

I will do that -- I will import (a part of) the Open Directory RDF structure dump.

When inserting a new menu item, do we need to check that the parent has depth < 6?

Yes, return FALSE if we can't save it.

When re-parenting, do we need to check that neither that item or any of its children will have depth > 6? What should the code do in this case?

Reparenting is another issue :)

pwolanin’s picture

Ok, tracking down the access bug- at least part of the problem seems to be that some node/%/X items in {menu} are getting assigned user_access instead of node_access as the access callback.

pwolanin’s picture

FileSize
67.88 KB

ok, a better patch. breadcrumbs work better (stupidly spent lot of time on this), and node access check should be happening right so the problem with the book module should be fixed. Menu module doesn't work yet- no reason to activate it.

Also, changed 'link_path' to 'href' and 'link_text' to 'link_title' to be more similar to the usage elsewhere in core by theme_links()/hook_links.

chx’s picture

FileSize
14.16 KB

Dmitrig01 reported http://dmitrizone.com/dump/Picture%202_.png .

I forgot one case in the menu tree hoarding, when you need to fail back more than one level, in the default install admin/user/user and logout just happens to stand like that. I removed ksort calls for testing ran insert into menu_links (menu_name, mlid, plid, href, router_path, disabled, external, has_children, expanded, weight, depth, p1, p2, p3, p4, p5, p6, module, link_title, options) values ('navigation', 500, 41, 'admin/user/user/1', 'admin/user/user', 0, 0, 0, 0, 0, 4, 1, 9, 41, 500, 0, 0, 'system', 'Users1', 'a:0:{}'); update menu_links set has_children = 1 where mlid = 41; and got the attached picture -- which is what we expect. Dmitri's bug is now fixed.

He also reported another, I will promptly fix that and then submit the patch.

chx’s picture

FileSize
66.75 KB

So this patch contains two bug fixes, one detailed above and the callback tree needed sorting, I have added that, this fixed some problems when access callbacks became 0 like on admin/user/profile.

pwolanin’s picture

FileSize
68.24 KB

I'm not sure how best to handle this, but note that when you go to a page with just a callback like: admin/user/profile/edit/1

Then the navigation menu tree is no longer expanded down to the level it was on the page admin/user/profile, and the breadcrumb just has "Home". Obviously, profile module itself could fix up the BC, but this doesn't seem totally satisfactory. Also, it's not clear the current code is handling MENU_SUGGESTED items correctly.

Perhaps we need to be putting callbacks into the {menu_links} user 'navigation' too? Then menu module will just have to know not to show them if they are type == CALLBACK vs. TYPE == SUGGESTED?

In this case, should the column in menu links be changed form 'disabled' to a more accurate 'hidden' or 'not_shown', or reverse the sen of it and make it 'shown' or 'visible' or 'visible_in_menu'? Attached patch changes it to 'hidden'.

Attached patch tries to fix all these issues. Note, we have to do a little double-check now in _menu_link_translate. Maybe there is a smarter way to avoid this problem when building the navigation menu? For example, exclude any router items with '%' except if they have a to_arg() function?

pwolanin’s picture

FileSize
75.18 KB

Follow on to the previous patch - as best I can tell, that's working (except My Account not showing again - hopefully this patch fixes that).

This patch adds to this the handing of menu link items set to be "expanded". No Drupal UI for this yet, just set expanded = 1 for some menu items via your DB interface to test. Creates a new pair of functions that parallel menu_tree_data and _menu_tree_data: menu_subtree_data and _menu_subtree_data.

This should be generally useful- for example: $output = menu_tree_output(menu_subtree_data('navigation'));
Should give you the rendered navigation menu where only items with expanded = 1 are expanded, independent of the current path/page.

Note also- disabling a module doesn't trigger menu_rebuild() - maybe a bug in system.module?

chx’s picture

FileSize
68.5 KB

Peter, sorry, but this is not how expanded needs to be handled. See my patch. Expanded does not require new processing code, just iterating a new query if there are expanded items. I never wanted to write this myself, but ah well, it's not too complicated...

chx’s picture

FileSize
29.61 KB

Screenshot of expanded in action.

webchick’s picture

Going through, found two more issues:
- My recent posts is gone from tracker, and after visiting any subsequent page, you get:

 # warning: Invalid argument supplied for foreach() in /Applications/MAMP/htdocs/head/modules/user/user.module on line 92.
 # user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1 query: SELECT * FROM users u WHERE in /Applications/MAMP/htdocs/head/includes/database.mysql.inc on line 161

... chx is fixing now.
- Attempting to add a path breaks horribly:

user warning: Unknown column 'link_path' in 'field list' query: UPDATE menu SET link_path = 'smooky' WHERE path = 'node/1' in /Applications/MAMP/htdocs/head/includes/database.mysql.inc on line 161.

chx claims it should not be trying to update menu at all, but menu_links. menu_links has no link_path field. it has a router_path field, but then it also has no path field. I gave up trying to fix it.

webchick’s picture

Status: Needs review » Needs work

Two others I forgot about:
- Apostrophes are double-escaped when used as a menu title (made a profile category "Let's dance" that came out as HTML entities for the apostrophe)
- There are a couple notices as search/user:

notice: Undefined offset: 2 in /Applications/MAMP/htdocs/head/includes/menu.inc on line 443.
notice: Undefined offset: 2 in /Applications/MAMP/htdocs/head/includes/menu.inc on line 443.

search/user/ is fine.

webchick’s picture

Ahem. search/user/[somename] is fine.

chx’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
70.09 KB

This patch does not serve aliased links at this point, so I removed the path code. I needed to add dynamic translation back to menu_translate but only when tabs are rendered. There is no a function which is used by menu_translate and menu_link_translate. This fixed the search tabs as well. The double escape I am not fixing it's a side effect of the localization patch: the title callback is check_plain and then we run it through l(). I will talk with Goba what's the best avenue to fix it.

I am RTBC'ing at this point because I fixed everything webchick was able to find with one sweeping fix -- actually since the moment I saw the changed menu_translate it nagged me.

Let me sum up what we have gained with this patch: an API which lets you add links to any menu and the ability to render said menu. As a bonus, we got a lot of things, most important is one query for tabs instead of many and expanded support.

Dries’s picture

Clearly, a lot of hard work went into this patch. That's great! :)

But, boy, this is a _lot_ of code, and much of this is hard to understand. It will take me several iterations to get this review right. I spent 45 minutes reviewing it and I doesn't feel like this review is particularly useful. I'll need to spend more time with it, but I have to run now.

My overall, initial reaction is: poorly documented. With better documentation and code comments, I'd have been able to get a lot more done in 45 minutes.

In fact, I can't comment on the engineering/architecture yet, as I've yet to figure out how exactly everything works. The lack of good code comments are a bit problematic. Without better code comments, I'll have to sit down and spend some hours reviewing this. I'll want to find a free evening for that.

For outsiders, the old menu system was hard to understand. But for outsiders, the new menu system also risks being hard to understand. At least, that's how I feel now, but I'm positive that I'll see how it all works fairly soon. ;-)

1. For example, _menu_translate() is documented to return a $map object but it can also return FALSE (which is not documented).

2. In the documentation '$to_arg_functions' should probably be '$to_arg functions' (space) as the variable is called '$to_arg' and not '$to_arg_functions'.

3. Documentation is sparse at points. What does _menu_link_flatten do, and how?

4. "Returns a rendered menu tree based on the current page." -- while I understand what you mean, it could do with being a bit more verbose. "based on the current page" might not be explanatory for everyone.

5. Shouldn't "menu_tree_output" be an internal function? I.e. "_menu_tree_output"? The function's PHPdoc does not help me understand it either. I had to read to code to understand that it is a helper function of menu_tree().

6. "Get the data representing a named menu tree". What is 'the data'? The stuff? :)

7. If would help if you could document -- in the code -- how the algorithm works. As this is what you are soliciting feedback for, it would help reviewers do their thing.

8. What is the performance impact of this patch? On a small or medium sized Drupal site with a dozen menu items? How much extra queries does it add? It seems to be database heavy. Will it slow down or speed up Drupal?

9. There are about a dozen TODOs in the code. Sure this is RTBC?

10. _menu_router_build seems key and it has no code comments whatsoever.

To make a long story short. I only had a first look at it, and I think I understand the bigger picture. I'll need to dive in and inspect the different bits and pieces into more detail. If you want to help me do that, focus on writing better code comments (this is going to be a requirement anyway).

Either way, good job on taking on this legendary task. Most of what I saw, makes sense -- I think. It's just that I have to convince myself a bit more/better by spending more time with this patch.

pwolanin’s picture

Status: Reviewed & tested by the community » Needs work

@chx- I disagree about the expanded link code.

You need to be able to distinguish the subtrees placed there because they are marked "expanded" to those placed there because they are part of the path to root in order to find the correct breadcrumb trail. Are the breadcrumbs working now for all cases?

Also, I think the subtree functions are very important for the API, even if we are not using them now.

Finally, I'll look further, but I don't understand why this code every needs to get the path alias if the links for tabs, etc are being generated via calls to l() which should look up the path

@Dries - for menu_tree_output, I removed the leading "_" in my most recent patch with the idea being that this should be an API function for rendering any menu tree/subtree rather than just a helper function. The thrust of moving towards something like menu_tree_data() is to be able to reuse the same information to generate the rendered menu, the breadcrumbs, book navigation, etc without doing any more queries.

chx’s picture

Status: Needs work » Reviewed & tested by the community

Peter, I believe there is no difference between an expanded tree and a tree which is just there. Think of it, when you stand on administer, you see tree elements below admin , so what? Breadcrumbs will work, why not? The menu_set_active_trail will iterate down until the current path/tab root and that's it. Expanded does not differ from what we already have.

Finally, I'll look further, but I don't understand why this code every needs to get the path alias if the links for tabs, etc are being generated via calls to l() which should look up the path

I do not understand a single word. The code does not get the path alias. What I said is that previous versions (like HEAD) had the ability to store aliased links. This is lost. To reintroduce, we need to look at path code. Later.

3. Documentation is sparse at points. What does _menu_link_flatten do, and how?

You found the only function which is not documented to death. Congratulations! It's an internal function.

TODOs are further patches.

_menu_router_build is also an internal function which you should never ever call and it has comments inside.

If someone else -- let's hope Peter -- wants to add even more comments, be my guest, but my time is limited at this point.

pwolanin’s picture

Status: Reviewed & tested by the community » Needs review

@chx - I need some time to test the code in terms of the menu tree, breadcrumbs etc.

I'll also try to add in as code documentation a version of this writeup of the method: http://drupal.org/node/141866#materialized

If aliased paths are stored, I'd only see this as part of a system of caching a rendered tree, but never in the {menu_links} table.

pwolanin’s picture

@chx- also, unless you fixed this, the help text isn't showing up when you're on the full path of the default tab.

For example, help text may show on 'admin/settings/filters/%' but not on 'admin/settings/filters/%/list'

chx’s picture

Let me make myself clear: my core coding time for the next two or four days is zero. And no, I have not checked help.

pwolanin’s picture

@chx - I understand- I'm just trying to think of all the relevant questions/concerns/bugs before I look at the code again.

chx’s picture

Peter, I believe only more comments per Dries' call and help texts by your call need attention. Everything else can come after. Code freeze is approaching and this patch is already huge.

riccardoR’s picture

There are still some issues with expanded and breadcrumb IMO:

- Administer > Categories > Edit a vocabulary
- Administer > Input formats > configure an input format
- Administer > Users > edit an user

(Note: patch #67 applies to #HEAD with 3 lines offset in user.module)

chx’s picture

If needed just rip the ~!@#$%^&*() expanded out of the patch , I totally did not want to do it (ever) especially not part of this patch but as Peter added it I had little choice but recode it.

pwolanin’s picture

@chx- it seems you didn't like the algorithm/method I used for expanded items? However, I think it works? Are there flaws in that code? Maybe this should have been saved for a subsequent patch, but I'm a perfectionist.

chx’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
71.94 KB

I fixed riccardoR's finding which obviously had nothing to do with the expanded code. I added a billion more comments. Re. DB heavy, not at all, actually, tabs are now cheaper. Why have you thought this is DB heavy? Expanded can cost you a few queries (max five) but -- there is a price to be paid for exotic features. Normally, not a single expanded query is executed. _menu_router_build is internal, there are comments inside where needed.

And no, we do not ask anyone to comment on the algorithm -- if we would have kept the matrix implementation you would expect them to review that? We agreed on this is not necessary. We are asking whether it works and it does. And unless you ask for even more comment, it is ready.

pwolanin’s picture

@chx - I didn't have any chance to code yesterday- I'll go through this last patch tonight for some final review/testing.

Owen Barton’s picture

One thing that I did notice was that this patch, although it looks huge (especially in terms of Kb) actually removes a significant number of lines.

Here is the ~count:
-628
+969

i.e. a total of 341 new lines of code, which I don't think is too bad, considering the amount of functionality this (re)enables.

pwolanin’s picture

Status: Reviewed & tested by the community » Needs work

I see some minor problems- here's one comparing menu.inc after my last patch to Karoly's last patch:

-        SELECT *, ml.weight + 50000 AS weight FROM {menu_links} ml INNER JOIN {menu} m ON m.path = ml.router_path
+        SELECT *, ml.weight + 50000 AS weight FROM {menu_links} ml LEFT JOIN {menu} m ON m.path = ml.router_path

I think we have to do a LEFT JOIN, since there will be no m.path in {menu} for an external link in {menu_links}.

riccardoR’s picture

@chx, @pwolanin: I am sorry for having created a misunderstanding with the word "expanded".
I have just realized that you were talking about the expanded link flag, while my feedback was about the normal tree expansion when navigating down the menu.

As I am here, I can confirm that the last patch fixes my finding.
Thanks

pwolanin’s picture

Ok, I'm getting my head around Karoly's way of getting the expanded items- does indeed seem better than what I coded. My only suggestion- rather than storing just a TRUE/FALSE in the 'menu_expanded' variable, why not an array of menu names?

However, I think function menu_set_active_trail() needs a slight adjustment, or all the active trail may show the expanded items, rather than the path to root for the current page in the active menu.

I still think something like a menu_subtree_data() function would be good for the API (though not necessary for this patch).

pwolanin’s picture

Status: Needs work » Needs review
FileSize
74.98 KB

I think this patch fixes all the issues I identified - I checked, and previously if the menu items were set to be expanded, the breadcrumb was totally wrong. Also I manually added external items to {menu_links} and they work with this patch.
- fixed query in menu_tree_data()
- fixed active trail/breadcrumb by setting a flag in _menu_tree_data() for each item
- use drupal_clone() in menu_get_item()
- rearrange a couple indices
- make the same help show on a page and on its default local task.
- implemented 'menu_expanded' as an array instead of boolean.

pwolanin’s picture

FileSize
7.19 KB

@chx - here a diff showing what changes from your last patch, _6, to mine, _7.

chx’s picture

FileSize
73.28 KB

I agree wholeheartedly with your changes -- but this

+  // Keep track of which menus have expanded items
+  if ($item['expanded']) {

part is not needed -- you always want to check for expanded menu names because what if I just switched off the last expanded menu item? (BTW. if someone is concerned why my patches are smaller, that's because bzr puts smaller header per files, but the patch itself is the same)

pwolanin’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
74.86 KB

Yes, it's probably simplest and most robust as you suggest.

Extremely minor changes in the attached patch- I fixed a spelling error in a comment and deleted one stray line of useless code.

  +      $tree[$index] = array(
  +        'link' => $previous_element,
  +        'below' => $below,
- +        'expanded' => '',
  +      );
Dries’s picture

Is it normal that the menu module is still broken? I applied the patch, did a fresh installation and went to the menu administration page: Unknown column 'visible' in 'where clause' query: SELECT m.*, me.disabled FROM menu m LEFT JOIN menu_custom me ON m.path = me.path WHERE visible = 1 OR (disabled = 1 AND admin = 0) ORDER BY mleft in includes/database.mysql.inc on line 161.

Other than the broken menu administration page, this patch seems to work. ;-)

chx’s picture

Yes menu is module broken.

pwolanin’s picture

I think in an earlier stage of the menu rewrite i remember that the checkbox for menu module was disabled on the modules page? Perhaps we can just do this again to avoid angst and confusion.

pwolanin’s picture

FileSize
75.26 KB

Attached patch adds a couple lines of temporary code to system.module to disable the menu module checkbox.

Gábor Hojtsy’s picture

Tried to look through what is happening in this patch. But it does seem to have evolved a lot farther then what chx set out in his five initial tasks. Maybe we can get an overview of what is happening here. I see a lot of changes are around, but maybe we can get a short architectural overview. Sure pwolanin and chx knows what concepts and approaches are changed, but I cannot make it from the patch.

I also noted 13 TODO items in the latest patch, some in groups of three, one in an empty stub function. Are these supposed to be filled in with later improvements in the 6.x timeframe?

pwolanin’s picture

@Gábor - the TODO items fall into 2 categories:
1) performance related (i.e. not necessary to have them done before the code freeze)
2) important functionality

This patch is a stepping stone towards a a follow-on patch that should (at the least) address all the TODO items in category #2 and re-enable the expected functionality in the menu module. Note, the goal is that menu module will be optional, and (for example) I think it would make sense to be able to enable it, add links to the primary links, and then be able to disable it to improve site performance while still having those primary links appear.

Overall this represents a necessary continuation of Karoly's initial rewrite of the menu system. Here's what it does:
It splits the "menu" between two tables: {menu} and {menu_links}. The {menu} table contains "router" items- in other words, the items that determine the correct page callback for a given path. The {menu_links} table contains the links that are displayed in menu blocks like the navigation menu, primary links, etc. By making this separation, {menu_links} can become quite large (for example, our goal is to rewrite the book module to save an actual menu link for each item in the hierarchy) without having a negative impact on page serving. In addition, only the items needed to render menu blocks/links are loaded from {menu_links}, thus minimizing memory usage.

pwolanin’s picture

@Gábor - also (quite frankly) this split was more difficult than Karoly described it as being initially. However, while some of the names used don't match what's in his 5 points, it all follows directly from his proposal.

Also, if it would be helpful for your review, I'd be willing to annotate (and maybe add more) TODO comments to make clear whether they are performance or function related. This change to the menu system will clearly impact other people's patches, so I think it's important to get it in now, and then build on it.

chx’s picture

The patch has nothing to do with the original post... There was a TODO in HEAD (and a mail to devel, long ago) asking for splitting router and link items and Peter implemented this. This lets us scale the new menu_links table to quite new sizes -- book with use this. As a collateral, multiple menus are supported.

Dries’s picture

I would be useful if we could add that high-level discription (router vs menus) at the top of menu.inc.

Also, if {menu} is use for router-stuff, why not call the table {router}? And if {menu_links} is used for menu-stuff, why not call that {menu}? :-)

chx’s picture

FileSize
75.58 KB

Added - changed comments to the top, changed table names. I truly hope this gets in now...

Stefan Nagtegaal’s picture

Perhaps my opinion doesn't matter that much, because I totally have no clue how the new menu-stuff works atm but wouldn't it be nicer if we prefix the new created tables with the modulename?
So that would make {menu_router} and {menu_links}.
I would love to see this for every core/contrib module, so examinating the database would be pretty easy and much easier to have a clue where to start looking at in the first place.

Just a thought, you can safely ignore this if you want to...

pwolanin’s picture

These tables are both defined by the system install and used by menu.inc (really part of system.module) and are independent of the menu module.

So, I'm not sure that "router" is any less clear than "system_router" or "menu_router", but I don't have strong feeling about how the table should be named.

chx’s picture

We never had anything similar, splitting a table by module. We can do that later for now all I care about is getting it in fast.

pwolanin’s picture

@chx - if I understand Stephen correctly, his suggestion is not to split the table, but rather that all Drupal tables should have a name that indicates which module "owns" it.

chx’s picture

Please, please get off table renaming especially sweeping ones and get this in finally!

chx’s picture

FileSize
75.61 KB

It applies still but not cleanly so I reroll.

Dries’s picture

Status: Reviewed & tested by the community » Needs work

I looked at the code once more, and I'm OK with it although I'm still not super-excited about the code comments. The function explanation seems decent, but the code comments in the function bodies seems somewhat lacking.

My review:

1. In the code comments, 'fail' should probably be 'fall'.

2. Elsewhere in Drupal core's database schema we use 'link' and not 'href' to denote a hyperlink.

3. 'user..' should be 'user.'.

4. "This function translates the objects in the map to current values with helper functions." -- Can we make this slightly more concrete? What are 'current values with helper functions'?

5. "When rendering a menu link, this function is similar to _menu_translate() but does other link-specific preparation." -- What is this supposed to mean? Please specify how it is different. In other words, what are these 'other link-specific preparations'?

6. "and dynamic paths are also changed accordingly." -- What do you mean with this? How are dynamic paths changed, and why?

7. "Build the data representing a menu tree" -- Sentence lacks trailing point.

8. In the comment module we use 'cid' and 'pid'. Here we use 'mlid' and 'plid'. I'd prefer to use 'mid' and 'pid' here.

9. 'has_children' should be 'children' -- we don't use 'is_hidden' either. We simply use 'hidden'.

10. 'link_title' should be 'title'.

Also, I'd like one other core developer to review the next iteration of this patch before I commit it. This will help guarantee that the code (and the code comments) make the new menu system accessible to new people. I want this person to look at the code changes and the code comments, not just click around a bit. I think this is important because we want to avoid a scenario where only 1 or 2 people can debug a menu system problem. This is an important patch so I'd appreciate it this could bubble to the top of our todo lists. Thanks.

Needless to say, this patch is pretty an amazing step forward. We're just trying to perfect it through review. :)

chx’s picture

    // If the link title matches that of a router item, localize it.
    if (isset($item->title) && ($item->title == $item->link_title)) {

I would keep title and link_title separate. For the other requests, I am too tired to even try to explain this in code comments properly. We have a handbook page and that should suffice . But of course not. However, I am not going to write these comments today. Or ever. I do not know.

pwolanin’s picture

@Dries:
re: #2 Elsewhere in Drupal core's database schema we use 'link' and not 'href' to denote a hyperlink.
I made this 'href' to be consistent with the usage by hook_link. This column can contain either a valid site path or an external URL. In other words, the $path parameter for l(). Aggregator uses uses 'link' as a column name, but I think this is always an external URL. Drupal module (which is being removed/changes?) uses it, but again it's for a URL which is always external to the site. I think {url_alias} used it at one point, but now seems to be 'src' and 'dst'.

re: #8. In the comment module we use 'cid' and 'pid'. Here we use 'mlid' and 'plid'. I'd prefer to use 'mid' and 'pid' here.
I disagree for two reasons. 1) As a new developer, I found the re-use of column names for unrelated IDs (e.g. vid =node revision ID or vid= vocabulary ID) a very real and unnecessary impediment to understanding the schema. 2) Karoly suggested the change to make the different role clear to developers who are familiar with the previous menu system schema.

re: #10. 'link_title' should be 'title'.
The column cannot easily be renamed 'title' since in the code we join to {menu} which has a 'title' column.

chx’s picture

Yes. I stand for mlid/plid. At one point we were discussing this patch over the phone and my mind just blowed from the name of the identifiers. Imagine someone who is not neck deep into this.

#9. 'has_children' should be 'children' -- we don't use 'is_hidden' either. We simply use 'hidden'.

No. Look at #children in drupal_render -- from 'children' I would expect to hold the actual children, this is just a flag.

pwolanin’s picture

Status: Needs work » Needs review
FileSize
79.21 KB

Ok, I worked on some of the comments, and fixed another minor bug or two. In particular, the default install profile didn't do a menu_rebuild. A menu rebuild needs to happen every time a new node type is added since a new router item is defined.

Also made the naming of the tables consistent: {menu_links} and {menu_router}. Thus, mlid and plid make sense as "menu link ID" and "parent link ID".

Put a temporary piece of code in system.module to prevent menu module from ever being activated.

chx’s picture

FileSize
78.17 KB

Worked on the comments w/ Andre Molnar.

andremolnar’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
78.1 KB

fixed a couple of tiny typos

Dries’s picture

I don't think my previous review is properly addressed. Some of them still stand.

pwolanin’s picture

@Dries - can you be specific and/or address the arguments Karoly and I made?

Dries’s picture

I'd like to see has_children renamed to children, and I'd like to see mlid and plid renamed to mid and pid, respectively.

Why do both routers and menu items need titles?

It's not clear whether andre actually understood the menu system and/or approves the changes.

chx’s picture

Children is expected to be a data structure that holds stuff with a common parent. is_children is a flag whether such entities exist. title in menu_router is defined in hook_menu, can be run through t(), title menu_links is entered by the user, not suited for t(). Andre seemed to understand the changes...

chx’s picture

Also, given that menu_router and menu_item get joined occassionally, renaming mlid and plid to mid and pid is a very bad idea, I believe.

pwolanin’s picture

@Dries -
'has_children' to 'children': I think Karoly's point is worth considering, but I don't feel strongly.

title in {menu_router} is used to generate the page or tab title - this is defined by hook_menu
link_title in {menu_links} is used to generate the link title in the visible menu block and breadcrumb and will (eventually) be changeable by the user using menu module, etc. Using the example of node links- every one would typically have the node title as the link_title, but every one will join to {menu_router} with path 'node/%/view' which is what makes the title 'View' show up on the default tab.

See my reasoning above for my mlid and plid are better.

riccardoR’s picture

Status: Reviewed & tested by the community » Needs work

Patch no longer applies because of http://drupal.org/node/137767 committed to HEAD.

Patching file 'profiles/default/default.profile'
Hunk #1 failed at line 111
riccardoR’s picture

I've just noticed that a warning is displayed every time menu_rebuild() gets called :

user warning: Table 'drupal6.menu' doesn't exist query: DELETE FROM menu in D:\var\htdocs\drupal_head\includes\database.mysql.inc on line 172.

The reason is menu_cache_clear_all() still referencing the old menu table.

function menu_cache_clear_all() {
  cache_clear_all('*', 'menu', TRUE);
}

The following modification seems to work correctly:

function menu_cache_clear_all() {
  cache_clear_all('*', 'menu_links', TRUE);
  cache_clear_all('*', 'menu_router', TRUE);
}
Crell’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
79.75 KB

I just went through and read menu.inc pretty much top to bottom. I think it has to be the most documented component we have now. :-) By and large I do understand what is happening (although I was at chx's talk at DrupalCon), and like what I see.

Regarding mlid & plid: I say keep them as is. Requiring 3 character primary keys leads to far too much confusion, especially if one has to start joining things. vid and vid is annoying enough. We don't need mid and mid and pid and pid, too.

Regarding has_children: $has_children is used throughout the PHP code. The database column should match it for clarity. Using $children would be horribly confusing when dealing with this sort of data structure. I don't have a problem with a has_children boolean column.

Attached patch is a reroll against HEAD that fixes the items riccardo noted.

ChrisKennedy’s picture

Status: Reviewed & tested by the community » Needs work

There are several typos and a modified settings.php included in #120. A lot of the comments would look better if they included a period to end the sentence too.

includes/menu.inc

If the link title matches that of a router item, locaize it. -> localize

An error occured loading an object -> occurred

see http://drupal.org/node/141866 for more. -> more information?

Don't show a link to the current page in the bc trail -> breadcrumb

We are on a tab -> should be on a new line.

TODO how do we hadle the case -> handle

theme_menu_local_tasks() -> doxygen indentation is off by one space.

Remove those items which router path does not exist any more -> Remove items if their router path does not exist any more

Mandatory key is only href and link_title. -> The only mandatory keys are href and link_title.

Find the router path which will serve this paths. -> "these paths" or "this path"

separate callbacks from pathes, making pathes ready for matching -> paths

chx’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
78.13 KB

Again I feel like in http://drupal.org/node/77919#comment-125579 -- why it is always my patches that get scrutinized to the last comma when incredibly broken stuff can get in just to be removed later (I will not name specifics, but it did happen lately). Nevermind. I am just grumpy as usual.

chx’s picture

Really nevermind. Drupal will get better and at one point I will get the patience needed for it... just there is little time until the freeze (my linked comment was also before a bit more than ten days before the freeze) and there is so much to be done.

Dries’s picture

Status: Reviewed & tested by the community » Needs work

Alright, committed to CVS HEAD. :)

Marking this as 'code needs work' until the documentation has been written.

bjaspan’s picture

This prevents HEAD from installing on postgres. Patch attached. The patch makes it install cleanly but I can't promise there are not other pgsql-related issues.

FYI, now that I'm paying careful attention to pgsql, I've noticed several core patches recently that create id columns as type int, not type serial, for pgsql. Remember, db_next_id() for pgsql *requires* that any column it is called to generate an id for be type 'serial'. This requirement has nothing to do with the schema patch.

moshe weitzman’s picture

Status: Needs work » Needs review
Dries’s picture

Status: Needs review » Fixed

Committed. Thanks! :)

pwolanin’s picture

I've started editing Karoly's documentation here: http://drupal.org/node/102338

Also, just opened a new follow-on issue for menu module, etc: http://drupal.org/node/144753

pwolanin’s picture

Split the follow-on patch into two parts: the one referenced above for menu.module, and this one for the necessary changes to menu.inc to support menu module: http://drupal.org/node/145058

Anonymous’s picture

Status: Fixed » Closed (fixed)