This is a really weird behavior, observed by me on real site's test-upgrade. A collision between Statistics and Tracker modules disrupts menu system so badly, that User-editing page doesn't show Profile-defined secondary tabs. (Took me whole day to track this down, surely menu system needs some sanity-check to avoid this re-appearing in contrib every other day - but that's for another issue.)

As for this bug here, I tracked the origin to Statistics module, which adds a sub-tab with path user/%/track/navigation, without ensuring that the parent and default-task neighbor entries are there. These are originally provided by Tracker module, which doesn't need to be enabled!

Filling this as critical might be debated, but certainly (in some configs) it completely kills access to user profile edits other than basic account info, making the Profile module useless.

Background: On my site, there's Statistics module enabled, because it's really useful - provides all sorts of admin logs like referrers / top pages / top users and the like. Tracker is NOT enabled, because it's pretty useless if using Views - all Tracker's functionality is replaced by customized views anyway, so no need to load extra code for nothing. So it's a pretty sensible config IMO, nothing extreme.

How to reproduce:
- Fresh 6.x-dev install
- Enable modules Profile and Statistics (but NOT Tracker!)
- Go to Profiles and add a new field
- Go to 'My account' and click 'Edit'.
Expected behavior:
Secondary tabs 'Account' and 'your_fields_category'.
What happens instead:
No secondary tabs. (If you guess the exact URL of the other tab, it works, but still no tabs rendered.)

How the bug happens, for your information:
- Statistics define a tab 'user/%/track/navigation'.
- Tracker is disabled, so the parent 'user/%/track' doesn't exist.
- _menu_router_build() notice the missing parent, and "helpfully" reparent the tab to 'user/%'.
- On page request for 'user/xx/edit/category', the menu_local_tasks() function iterates through all tabs, presuming that tabs of the same level have equally-long paths:
* First secondary tabs on 'user/%/edit/***' are rendered and stored into array, with the key = number of path elements being 4.
* Then it go to parent-level and render primary tabs for 'user/%/***', whose number of path elements is generally 3, excepting the re-parented entry 'user/%/track/navigation' having 4 elements. Unluckily, that entry goes last, so the number 4 remains in variables, and is later used as array key for storing primary tabs. Thus, previously rendered secondary tabs are OVERWRITTEN by primary tabs.
* The resulting array (only one element in this case) is re-sorted to gain zero-starting keys, so primary tabs appear correctly as element #0. Secondary tabs are gone.

The fix: The question of menu system being disrupted so easily and difficult-to-track goes into another issue. But in the first place, defining a tab with non-existing parent is wrong. So I'm attaching a patch for statistics.module, which checks for the Tracker module existence, and moves the offending tab from (wrong) 'user/%/track/navigation' to (correct) 'user/%/track' if Tracker is not enabled. So, the tab is simply elevated to primary-tab position, if there's no lower structure to integrate into. The resulting UI is exactly the same as before, only the tab is now re-parented correctly and so doesn't cause problems.

Patch attached.

CommentFileSizeAuthor
statistics-menu.patch898 bytesJirkaRybka

Comments

JirkaRybka’s picture

I just created the other issue for menu-sanity check: http://drupal.org/node/179474

webchick’s picture

Wow, what an obscure bug. Nice sleuthing!

However, IMO this fix is not quite right... we shouldn't change the path of a page depending on what other modules are installed. If I bookmark user/1/track I expect it to be the same thing every time I return to it. Once I enabled tracker module, the contents of this page would be completely different, no?

I have a copy of the drupal.org testing install profile installed, which has the CVS module, which puts a user/1/track/code path. In 5.x, when I disable tracker module, this path still works, and when I go to user/1/track (which doesn't exist), I'm simply taken to user/1. I believe this is what the menu system in 6 ought to do as well, rather than switching around locations of stuff. Then again, I don't have a user/1/track/navigation in my install.. was this something new added for 6, or..?

JirkaRybka’s picture

Well, I believe (didn't check for time matters now) that this is an old bug, existing long before. That entry is simply broken under described conditions. But since Drupal 6 got a brand new menu system, this started to cause problems.

For thoughts about making D6 menu system behave just like D5 (amongst other ideas), see the issue linked in #1. But that would be a bigger change I'm definitely not going to do now, and still this tab is technically broken.

The only other way for this issue here (that I can think of) would be to define a dummy parent 'user/%/track' from Statistics (conditional for Tracker's absence again), or move the whole thing to a path of its own (not depending on Tracker at all), but I can't see why.

The path changes, that's true, but I believe that it's somehow normal if pages appear/disappear on modules enable/disable operation. You're not supposed to do such changes to your config in production, without expecting a few bookmarks to break, or am I missing something?

I'm not changing the patch now, until we agree on some other way to go (if we are going to), or feel free to provide an alternative. Thanks.

JirkaRybka’s picture

Forgot to say: 'user/%/track/navigation' is a regular tab from Statistics module (dependent on some permissions and stuff), existing long ago.

If the CVS module (which I haven't) adds 'user/1/track/code' without checking for valid parent, then it's doing the wrong thing again, just like Statistics, and needs to be corrected too.

Or: Menu system documentation needs to mention that it's legal to provide parent-less tabs. Being THAT the case, menu_local_tasks() needs a major rewrite urgently.

webchick’s picture

I'm not changing the patch now, until we agree on some other way to go (if we are going to), or feel free to provide an alternative. Thanks.

I guess my alternative is that we should fix the broader issue you pointed to. I don't think we should hack around the problem for this one pair, knowing that this is going to bite us in the rear end over and over again in contrib. CVS module will do this same behvaiour in 6.x, as one example.

The fix should be to remove the requirement that a parent path exist in order to define a child path (which is how the menu system worked in 5). If you attempt to go directly to a URL that doesn't exist, it should take you to the next parent that actually does exist (e.g. user/tracker should be go to user).

If that is too cumbersome/impossible with the new menu system, then I guess we'll have to sort something else out. But no, imo the path cannot change...

The path changes, that's true, but I believe that it's somehow normal if pages appear/disappear on modules enable/disable operation. You're not supposed to do such changes to your config in production, without expecting a few bookmarks to break, or am I missing something?

It's not quite this cut-and-dried:

  • Consider documentation in the handbook for the end-user that wants to link directly to the page. "Go to the user statistics page which might be here or else here if your site administrator has enabled the tracker module." How would an end user ever know that?
  • When trying to duplicate bugs, it's very helpful to have the full menu path. If I say "The table is all screwed up at user/1/track", and user/1/track is a completely different page in your installation, how can you verify my bug report?
  • I've been a user on drupal.org for many years, and have bookmarks in my browser to things like my statistics page. When server load gets too high, they temporarily disable the tracker module. Now my bookmarks are busted.

In short, dynamically changing menu paths around is going to cause way more problems than it solves, especially if contrib has to resort to the same tricks. Let's fix this properly in http://drupal.org/node/179474.

chx’s picture

Status: Needs review » Closed (duplicate)
JirkaRybka’s picture

Status: Closed (duplicate) » Needs review

OK, changing paths was a rather nasty workaround. ;-)

Now, there's a lot of progress in http://drupal.org/node/179474 , fixing the menu system to accept these entries with no problems. So if that one gets in, I'll mark this issue here as fixed, no need to change paths then.

Let's wait for now...

JirkaRybka’s picture

Status: Needs review » Closed (duplicate)

Another cross-posting, sorry...

JirkaRybka’s picture

Status: Closed (duplicate) » Fixed

As http://drupal.org/node/179474 was commited, and fixes this bug (I checked), I would call this fixed. :)

Anonymous’s picture

Status: Fixed » Closed (fixed)