This is a split-off of fixes that were originally in:

the bugs to be fixed:

*every system-defined item has a "reset" link (even when not edited)
* the drop-down for picking a parent isn't ordered right
* the menu_otf form in the node form is very big and unwieldy, and located way at the bottom

I think these are all fixed, though agentrickard mentions possible additional bugs:

1. resetting an edited default item causes the "expanded" yes/no column to vanish in the list view -- see screenshot. But they came back after I created a new menu (seems like a menu rebuild issue).
2. Access denied pages still force strange behavior for primary links, as the top-level (parent) Navigation items appear as primary links.

note, additional bug #2 is prevented, at least in some cases, by this patch: http://drupal.org/node/148678

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pwolanin’s picture

oops - link to original issue: http://drupal.org/node/147657

pwolanin’s picture

FileSize
18.95 KB

missing a piece of the patch- menu module should be enabled by default too.

flk’s picture

just found this problem while trying to edit a dynamic item: ('My Account', 'user/%')
on submitting the form a foreach error occurs due fact that the path gets passed to user_load since user_load does not check if the % is not integer it errors out...this and similar problem is solved here: by http://drupal.org/node/148678
On applying that patch though a further error occurs because the function menu_get_item will return falls for paths that contain dynamic display.
I explained this a bit more @ http://drupal.org/node/148678#comment-259354

flk’s picture

first of I think i found another bug, when editing items descriptions are not saved.

in regards to the problem of dynamic links i have tried attacking (i remember vaguelly talking about with pwolanin/chx the other night) it by creating a function that checks whethere link_path is dynamic or not (this would replace $item = menu_get_item($path) -> $item = menu_valid_path($path in the _validate ) ),

function menu_valid_path($path){
  $dynamic = FALSE;
  if (preg_match('/\/\%/', $path)) {
    $dynamic = TRUE;
  }
  
  if ($dynamic){
    $item = db_fetch_array(db_query("SELECT * FROM {menu_router} where path = '%s' ",$path));
    // $item['access'] needs to be defined here
  }
  else {
    $item = menu_get_item($path);
  }

  return $item;
}

The only problem is i cant seem to figure out an easy way to check the access of a dynamic link....:/

flk’s picture

FileSize
20.31 KB

rerolled against head, also contains fix bug reported in #3.

webchick’s picture

Confirmed that this also fixes the notice: Undefined index: delete message when creating a node as noted in http://drupal.org/node/152281

flk’s picture

hmm i was trying to trace the disappearing description problem but it seems that it might have been caused by something on my system (me messing about :P).
installed this patch on fresh head and descriptions are saved fine.

pwolanin’s picture

FileSize
34.83 KB

After discussion with Karoly on IRC - normalize all the paths, so we use load functions rather than declaring lots of new router items.

Also, use paths like admin/build/menu-customize/$menu_name for each custom menu, to avoid potential name conflicts on admin/build/menu/*

pwolanin’s picture

FileSize
36.96 KB

last patch missed a few things- this one might work.

Note, also the menu_link_validate needs to be re-written (we can't rely on % being part of the link path)

pwolanin’s picture

Wait- I'm wrong for the validation. We can rely on '%' in the current code. to_arg functions can only exist with a wildcard path.

webernet’s picture

Title: fixes that make menu module work in D6 » Fixes that make menu module work in D6
Status: Needs review » Needs work

Editing "My accounts" item title:
- notice: Undefined index: options in \includes\menu.inc on line 539.
- redirects to "admin/build/menu/navigation" instead of "admin/build/menu-customize/navigation"

Disabling "My accounts":
- redirects to "admin/build/menu/navigation" instead of "admin/build/menu-customize/navigation"
- item is not flagged as customized (therefore no reset link)

Adding an item from "admin/build/menu-customize/navigation/add":
- warning: mysqli_real_escape_string() expects parameter 2 to be string, array given in \includes\database.mysqli.inc on line 362.
- The entire list of items in Navigation ("admin/build/menu-customize/navigation") disappears after creating a menu item for node/1

Adding an item from "node/1/edit":
- OK
- deleted OK from "node/1/edit"
- delted OK from "admin/build/menu-customize/navigation"

As noted in the original issue - Access denied pages cause the top-level (parent) Navigation items to appear as both the primary and secondary links.

pwolanin’s picture

Status: Needs work » Needs review
FileSize
31.56 KB

fixed, I think, the problems with the add/edit form.

webernet’s picture

Status: Needs review » Needs work

General:
- Redirects go to "admin/build/menu/navigation" instead of "admin/build/menu-customize/navigation"
- Disabling/Enabling system menu items doesn't flag them as customized, therefore no reset link.
- Why can I delete the navigation, primary links, and secondary links menu items?

Editing a menu item:
- warning: Missing argument 4 for menu_edit_item() in \modules\menu\menu.module on line 248.
- Only possible parents for any menu item are "Root" and any disabled item (ie. "Compose tips").
- After saving a change --> notice: Undefined index: options in \includes\menu.inc on line 539.

pwolanin’s picture

Status: Needs work » Needs review
FileSize
37.21 KB

In this patch, the links to the menus are created as just normal links. They are always listed at /admin/build/menu, so they are not really needed. This seemed cleaner to me than creating a whole set of router items for each one. It also makes the code more compact, since we can use the %menu notation to get the data loaded. Even if they were router items, the admin could choose to disable or move them.

I think I tracked down all the bugs mentioned above.

webernet’s picture

Status: Needs review » Needs work

On install:
* user warning: Unknown column 'mlid' in 'field list' query: INSERT INTO menu_custom (menu_name, title, description, mlid) VALUES ('navigation', 'Navigation', 'The navigation menu is provided by Drupal and is the main interactive menu for any site. It is usually the only menu that contains personalized links for authenticated users, and is often not even visible to anonymous users.', 0) in \includes\database.mysqli.inc on line 154.
* user warning: Unknown column 'mlid' in 'field list' query: INSERT INTO menu_custom (menu_name, title, description, mlid) VALUES ('primary-links', 'Primary links', 'Primary links are often used at the theme layer to show the major sections of a site. A typical representation for primary links would be tabs along the top.', 0) in \includes\database.mysqli.inc on line 154.
* user warning: Unknown column 'mlid' in 'field list' query: INSERT INTO menu_custom (menu_name, title, description, mlid) VALUES ('secondary-links', 'Secondary links', 'Secondary links are often used for pages like legal notices, contact details, and other secondary navigation items that play a lesser role than primary links', 0) in \includes\database.mysqli.inc on line 154.

On /admin/build/menu:
* notice: Undefined variable: content in \modules\menu\menu.module on line 154.

pwolanin’s picture

FileSize
37.06 KB

doh - seems I keep missing some little details (earlier patch included an extra column in menu_custom). Attached patch should solve those problems.

However, something funny happens when I enable/disable items.

webernet’s picture

Getting closer... ;)

Editing the "My account" menu item (other items appear OK):
* notice: Undefined index: options in \includes\menu.inc on line 539.

Reseting a parent menu item:
- Made it appear as though it wasn't a parent (no expansion arrow / empty expanded column), even though it still has children.

Disabling "Administer":
* notice: Uninitialized string offset: 0 in \includes\menu.inc on line 506.
* notice: Uninitialized string offset: 0 in \includes\menu.inc on line 513.
* notice: Uninitialized string offset: 0 in \includes\menu.inc on line 514.
* notice: Undefined index: load_functions in \includes\menu.inc on line 330.
* notice: Undefined index: access_callback in \includes\menu.inc on line 363.
* notice: Undefined index: access_arguments in \includes\menu.inc on line 369.
* warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, '' was given in \includes\menu.inc on line 376.
* notice: Undefined index: link_title in \includes\menu.inc on line 536.
* notice: Undefined index: options in \includes\menu.inc on line 539.

pwolanin’s picture

the latter set of warnings is what's really annoying me - see like bad data is getting loaded from the table when trying to build the tree. Maybe something about the left join to {menu_router}

Also, maybe we need a better definition of reset - what should happen if an item is reset, but its parent has been moved? It should go back to its original parent and properties, but that's all we can do.

keith.smith’s picture

Applying this patch on a fresh HEAD checkout cured at least the two following issues for me:

  • pre-patch, editing a newly created node resulted in node system paths being displayed by path module, but without a path Title (a required field on this form); one would have to enter a Title to resave the node
  • pre-patch, menu items created to lead to new nodes had very strange vertical spacing both before and after the item, at least on Firefox
pwolanin’s picture

Status: Needs work » Needs review
FileSize
40.76 KB

Ahh, finally tracking down the bug - a bit subtle - the big ugly error webernet was reporting occurred when, for example, /admin was disabled. Part of the problem was that the children of /admin we still being loaded and then the menu for display in the block was messed up when we went to /admin/build/menu.

The fix - need to change a couple queries and the access check function. Items need to be pulled form the table even if they are disabled - that way we can exclude them AND their children from display in the menu block, etc.

I also reworked the "reset" functionality.

pwolanin’s picture

FileSize
39.5 KB

One last fix - the ordering of links in menu blocks was a little broken - was using 'title' instead of 'link_title' (thus, a node link would be ordered using the router item title of 'View'), and also PHP has a case-sensitive sort, so I think it makes sense to lowercase all the strings (otherwise 'hello' comes after 'My account').

-    $tree[$previous_element['weight'] .' '. $previous_element['title'] .' '. $previous_element['mlid']] 
+    $tree[$previous_element['weight'] .' '. strtolower($previous_element['link_title']) .' '. $previous_element['mlid']]
webernet’s picture

Status: Needs review » Needs work

Clean install --> "Menus" item appears as though it isn't a parent (no expansion arrow / empty expanded column), even though it has children.

After Editing "My account": notice: Undefined index: options in \includes\menu.inc on line 539.

Can't add a link to the front page (path=)

Delete a menu item for node/1 from admin/build/menu-customize/navigation while node/1/edit is open. Check the delete box on node/1/edit and submit. Item is recreated! (Expected: Item remains deleted and possibly provide a message)

Delete a menu item from node/1/edit while admin/build/menu-customize/navigation is open. Attempt to delete from admin/build/menu-customize/navigation. Results in "Page not found". (Expected: Notification/error message)

Attempted to delete a system menu item by going directly to admin/build/menu/item/51/delete. Confirm form is displayed, click delete, "The menu item Themes has been deleted." is displayed, although it wasn't actually deleted. (Expected: "Access denied")

pwolanin’s picture

FileSize
40.1 KB

Webernet - thanks for finding these bugs!

Patch attached so that the delete confirm form now checks whether it's a system item and gives access denied.

The item being re-created (adfter being deleted) when marked for deletion in the node form seems to be a FAPI3 issue - you can avoid having the item re-created by previewing the node form once before delete the item at the admin interface. I think the problem is that upon submit, FAPI builds a new form for validation/submission. However since you've removed the item from the menu, the checkbox doesn't appear. If you preview, FAPI caches a copy of the form. So we can work around this problem by setting $form['#cache'] = TRUE, but I think FAPI should reject the form.

form_alter and nodeapi code changed to some to deal with this and to delete all links to a node when it is deleted.

the error with unserialize is happening because the of the validation code trying to account for dynamic links - it calls menu_link_translate

For me, on a clean install, I see the arrow in front of 'Menus', so I'm not sure about that problem.

pwolanin’s picture

Status: Needs work » Needs review
FileSize
42.22 KB
  • fixed last (I hope) redirect path issues
  • handle the special path
  • fix code so that the 'weight' column from {menu_router} doesn't clobber the one from {menu_links}
  • fix error message about missing index 'options'

note, a bunch of these fixes are in menu.inc, so I hope chx will review it too.

webernet’s picture

Everything seems to be working properly - I haven't come across any errors/warnings/notices.

pwolanin’s picture

FileSize
42.2 KB

very minor change as discussed with webernet on IRC - alter menu_nodeapi on $op == 'delete' so that only links created by menu module are deleted. Any other module creating links to nodes should do its own cleanup, and may also need access to its links before deleting them.

webernet’s picture

Status: Needs review » Needs work

No longer applies cleanly, needs to be rerolled.

pwolanin’s picture

Status: Needs work » Needs review
FileSize
42.16 KB

re-rolled for new confirm form params

webernet’s picture

Title: Fixes that make menu module work in D6 » Menu - Fixes that make menu module work in D6

Retested - No errors/warnings/notices that I can find.

chx’s picture

Status: Needs review » Reviewed & tested by the community

If it works -- the code looks good.

pwolanin’s picture

FileSize
42.43 KB

per discussion with hunmonk (Chad) on IRC - a very minor change to bring the patch into conformity with the new deletion API - hook_nodeapi on $op == 'delete' should call drupal_delete_add_callback() to define a callback that deletes menu items pointing to the node, rather than deleting them immediately.

pwolanin’s picture

FileSize
47.63 KB

per request of Steven in IRC, added more code comments to menu_tree_page_data() and meu_tree_all_data().

Also, fixed one minor bug that was causing the Navigation links to show up in the Primary and Secondary links on some 'Access denied' pages.

pwolanin’s picture

FileSize
51.63 KB

And since we're looking at code comments - this patch should fix them all per Drupal style so they all end with a period.

pwolanin’s picture

FileSize
51.75 KB

re-rolled patch so it applies cleanly after changes to confirm form params. Also, double-checked functionality on on PHP 5.2/MySQL 5.0.

pwolanin’s picture

FileSize
58.61 KB

Further discussion with Steven in IRC - adds doxygen comments for all functions, use drupal_strtolower(), and add a TODO relating to the need to sort menu tree siblings based on their localized titles.

pwolanin’s picture

Note that this patch is required to get menu module to work, period. Obviously, there are additional UI and performance improvements to be made. Follow on issues for once this patch is in:

  1. Improve performance of access checks and add localized sorting
  2. Optimize menu queries and indices
  3. Improve menu module UI and usability
  4. Convert menu link deletion to Deletion API
pwolanin’s picture

webchick’s picture

Priority: Normal » Critical
pwolanin’s picture

FileSize
59.49 KB

minor re-roll (1 line addition to system.install) to conform with this patch: http://drupal.org/node/150210

pwolanin’s picture

FileSize
61.28 KB

Jeff Eaton noticed a cut-n-paste error in function menu_tree_check_access from when I wrapped function _menu_tree_check_access() in this public function. This also similarly wraps function _menu_tree_data() with a non-recursive public function function menu_tree_data() so that the code looks like $tree[$cid] = menu_tree_data() rather than list(, $tree[$cid]) = _menu_tree_data()

pwolanin’s picture

Additional possible follow-on fixes needed:

Use API function to delete menu links during rebuild: http://drupal.org/node/155621

Improve menu code to handle callback breadcrumbs: http://drupal.org/node/155624

pwolanin’s picture

note for the curious, here's a summary of past and current menu system issues: http://groups.drupal.org/node/4850

eaton’s picture

I've just gone through and added a number of items to several different menus, created a custom menu of my own, etc. Things seem to be working fine, although using wildcards still generates an error. To see this in action, add user/% to the primary links menu:

notice: Undefined index: external in /Users/jeff/Sites/menu/modules/menu/menu.module on line 702.

Adding the item DOES work, though, and permissions etc are all applied properly.

pwolanin’s picture

FileSize
61.03 KB

function menu_valid_path requires a very small change to eliminate this warning.

      $item['external']   = FALSE;

not

      $item['external']   = $form_item['original_item']['external'];
eaton’s picture

That fixes the only problem I was able to find when working my way through. Kudos.

A big +1. Menu editing is way, way cleaner now.

cburschka’s picture

I'm probably not looking hard enough, but is $form_item['original_item']['external'] ever set when adding a new item?

What I'm seeing is this:

257: The edit form builder initializes an empty menu item. It doesn't have an 'external' key.
264: The edit form builder puts the item into $form['original_item'].
326: The form validator calls menu_valid_path on the form values.
702: menu_valid_path tries to access the 'external' key of 'original_item'.

Should the 'external' key be placed into the initializing array in the form builder?

pwolanin’s picture

we only get to this part of the if/else branch in the validation function if we've already checked and found that the path is NOT external. We only need to set the value so that _menu_link_translate doesn't throw the same warning.

cburschka’s picture

Whoops, too slow. Never mind.

pwolanin’s picture

FileSize
61.15 KB

previous patch still applies, but with fuzz, after hook_help patch. Attached is a re-roll that applies cleanly.

pwolanin’s picture

Status: Reviewed & tested by the community » Needs work

patch borked by deletion API roll-back

cburschka’s picture

FileSize
61.06 KB

If the rollback had any actual logical impact, then the patch attached will not work correctly (even worse, it'll seem to apply cleanly and then break the system without obvious reasons); because I haven't understood a tenth of the new menu system.

But if, as it looked to me, it was merely a matter of a few collisions where the same line was changed in both modifications, then this should be a clean (if painstakingly resolved) re-roll.

I've tested this patch, especially focusing on changing, saving and deleting a menu link since those were the hunks that failed. All worked for me.

cburschka’s picture

Status: Needs work » Needs review

*Sorry, by logical impact, I mean impact on the logic changes made by this patch. Also, forgot to set the flag back to CNR.

cburschka’s picture

*Sorry, by logical impact, I mean impact on the logic changes made by this patch. Also, forgot to set the flag back to CNR.

pwolanin’s picture

Status: Needs review » Needs work

I have not looked yet, but the only code change should be associated with menu_nodeapi and the Deletion API callback function that was being used. Essentially - the code in that callback should be moved back into menu_nodeapi.

pwolanin’s picture

Status: Needs work » Needs review

cross-post

cburschka’s picture

FileSize
60.84 KB

CNW was actually correct, since my version still incorrectly used the deletion API in nodeapi. Ironically, this change was one of the hunks that *didn't* get broken by the rollback, so I didn't notice it on resolving only the conflicts. I also didn't think of testing the node-creation/deletion of menu links, or I would have noticed.

I've put the code of the deletion callback back into the 'delete' case of nodeapi, and removed the callback; now it should be fine.

cburschka’s picture

FileSize
60.84 KB

menu.inc was put under the spell-checker, and it just so happened to be that this patch appended a period to one of the misspelled comments, causing a conflict.

Re-roll fixes this. I hope this patch can go in soon, or we'll spend more time re-rolling than actually improving it. ;)

RobRoy’s picture

Status: Needs review » Needs work
FileSize
58.72 KB

Bugs fixed in this patch:
- Menus link in admin overview said ". as well as" instead of ", as well as".
- /admin/build/menu/item/22/reset says Array for confirm form text, link and submit handler redirect were missing trailing slash, submit handler included hardcoded "navigation"
- Changed "Root" in parent select to "" to match what taxonomy.module uses
- Fixed an extra "." in Doxygen
- Moved menu OTF fieldset down as first below body, does not belong below title IMO
- Renamed OTF fieldset to "Menu settings" as "for this post" seems redundant to me

Tasks I did successfully:
- Edited a menu, menu item
- Reset a menu item
- Added a menu item
- Disabled/enable menu item
- Deleted a menu, menu item

Bugs mentioned in initial post that seem fine (I didn't read whole thread):
- Parent dropdown seemed ordered right
- Menu OTF seemed good (I moved it down though)
- Reset expanded menu item and "No" came back fine
- Went to 403 page and didn't see anything wacky

Bugs I still see:
- How do I delete a menu? Too tired to code this tonight...

pwolanin’s picture

We need to have a serious discussion about where to place the fieldset. I moved it up because its previous placement made it hard to notice for new users. Menu module will be enabled by default and should be (I think) considered the default tool for creating site structure. So I think the fieldset needs more prominent placement - the placement I proposed was essentially where the taxonomy fieldset and similar are placed.

theborg’s picture

What is the status now for the bugs?

An observation, why did you choose to link 'menu_custom' and 'menu_links' by menu_name and not mlid?

RobRoy’s picture

I like the fieldset below the content fields. IMO that's where it belongs, but I could be convinced otherwise I'm sure and don't think that should hold this up.

cburschka’s picture

Whether you want to create a menu item for the node depends very much on its type, since menus are for a static site structure. Blog entries are almost never put into menus, book pages might be on occasion, pages are very often. From the viewpoint of a user, it makes little sense to make a menu item for a news entry, but a lot of sense to place a static page somewhere in the sitemap.

Therefore: Could the fieldset be on top for 'page' type nodes, and below for everything else? There may be a good case for hard-coding this.

cburschka’s picture

FileSize
60.92 KB

This patch implements the above suggestion on top of patch #58, so skip this one if the suggestion is baloney.

'#weight' => $form['#node']->type == 'page' ? -2 : 5,

-2 was the weight it had prior to patch #58 (top of content), and 5 is the weight in #58.

pwolanin’s picture

FileSize
63.31 KB

Attached is my own re-roll for the API roll-back, and incorporates a number of the minor fixes listed above.

Note, I want the fieldset to be more prominent at the top, and since node types can be changed, it does not seem sensible to hard code node-type behaviors.

Per discussion w/ chx - next step will be all menus in one drop-down.

pwolanin’s picture

Status: Needs work » Reviewed & tested by the community

actually, the back above essentially brings us back to the patch in #49, and since both Karoly and Jeff Eaton were satisfied with that as an initial patch, it probably makes sense to deal with UI issues (e.g. all menus in one select) as more discrete follow-on issue.

Here's a re-listing of the follow-on issue to be handled once a version of this patch is committed:

Improve performance of access checks and add localized sorting: http://drupal.org/node/154469
Menu system UI problems - moving items between menus http://drupal.org/node/151055
Improve menu module UI and usability http://drupal.org/node/154471
Optimize menu queries and indices http://drupal.org/node/154470
Use API function to delete menu links during rebuild: http://drupal.org/node/155621
Improve menu code to handle callback breadcrumbs: http://drupal.org/node/155624
Allow custom menus to be deleted: http://drupal.org/node/156626

pwolanin’s picture

Status: Reviewed & tested by the community » Needs work

webernet found some cases which the last patch reverted typos that were fixed in a more recent commit, and also problems with the menu item reset confirm form and custom menu editing

Dries’s picture

Status: Needs work » Fixed

I've committed this patch so let's deal with the remaining issues in follow-up patches. Thanks guys! :)

pwolanin’s picture

Thanks Dries!

let's start with this one-
custom menus - error in submit function: http://drupal.org/node/156770

webernet’s picture

Anonymous’s picture

Status: Fixed » Closed (fixed)
Bevan’s picture

rmjiv’s picture

It appears that this workaround of caching the form is breaking CAPTCHA integration. Is there a better solution to this problem than just caching the form?

cilefen’s picture