When I make changes to a menu using Power Edit then save, the changes are not applied to the menu. The Power Edit form reloads without error after the save. However the changes are not displayed in the reloaded form, which reverts back to its original contents.

PHP error reporting is enabled but no error messages are displayed.

I'm experiencing this issue with both 6.x-2.2 and with 6.x-3.0-unstable3.
The menu appears to edit ok in the standard Drupal menu editor.

The Power Edit menu was previously used up to this point without issue and continues to work with other menus. Maybe there's something specific with this particular menu, perhaps a recent change, that has caused the problem?

If anyone has any suggestions for debugging this I'm happy to take advice, for example inserting debug if this will help get to the bottom of it.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

donquixote’s picture

I currently have no idea why this would happen, but I have some ideas for debugging:
- Check the contents of the POST data with Firebug.
- Put a debug statement in the submit handler (something like menu_editor_form_submit(), I guess), and check if it has been called. This is the place where you should dig.

Definitely run your tests with the 6.x-2.2 version. The 6.x-3.0 contains some experimental changes, that are not useful for the general public at this moment, so you can ignore this branch altogether.

As I understand, there is one menu (or some) where the module works, and another where it does not work. Thus, it will be useful to run each test with each of these menus and compare.

You should also look if there is anything special with that menu. Does it have an unorthodox machine name (with special characters, etc)? Can you look into the database, if there is anything that stinks?
The two "special menus" are usually navigation and admin_menu. I usually would recommend to not touch them at all with any editor.

sakadava’s picture

Hi donquixote,

Thanks for getting back to me - I appreciate it.

1. I switched back to 6.x-2.2

2. I placed a debug line in menu_editor.admin.inc at line 308, right at the top of menu_editor_overview_form_submit(). The debug line doesn't get called for the menu for which Menu Editor doesn't work, but it does get called for the menus that Menu Editor does work properly. So the submit handler is not getting called. Why would that be?

3. I used HttpFox to trace POST parameters. Both working and non-working POST parameters looked pretty similar to my untrained eye - a bunch of mlid-xxxx for link_title, link_path, description, hidden, weight etc. corresponding to the form contents, and at the bottom:
op = Save configuration
form_build_id = form-xxxxxxxx (some big hex number)
form_token = xxxxxxxxx (some other big hex number)
form_id = menu_editor_overview_form

Any suggestions for the next step?

donquixote’s picture

2. submit handler not called.
One reason could be that the form did not validate. You can debug the validation handler function, and let me know where it fails.

Looking at the code ...

function menu_editor_overview_form_validate()
function menu_editor_validate_item()
function menu_editor_overview_form_validate_new_item()

The last one is quite interesting..

<?php
function menu_editor_overview_form_validate_new_item($item) {
  // TODO: add some sanity checks
  return true;
}
?>

Ouch. this looks unfinished. But probably not as bad, noone complained yet.

-----------

What we need to look for in the validate handlers is the form_set_error().
The only one I can find is in menu_editor_validate_item(), if the link path does not validate. This is where you should dig further.

-----------

<?php
function _menu_editor_valid_weight($element, &$form_state) {
  if ((isset($element['#value']) && $element['#value'] !== '') || !empty($element['#required'])) {
    if (!preg_match('/^\-?\d+$/', $element['#value'])) {
       form_error($element, t('Weight has to be an integer value.'));
    }
  }
}
?>

This one complains if you have something in the weight field that does not look like a number.
The weight field is usually hidden when the tabledrag javascript kicks in. You could try the form without js, to see if there is anything strange in the weight fields.
And of course you can do some debug in this function.

sakadava’s picture

Thanks again.

So I've placed debug lines on menu_editor_overview_form_validate(), function menu_editor_validate_item() and function menu_editor_overview_form_validate_new_item().

On the errant menu, none of these functions appear to be invoked.

But I've confirmed that they do get invoked on the other menus - the ones that do work correctly with Menu Editor.

So it appears that for this particular menu none of the validate functions are getting invoked.

Do you have any suggestions for the next step to figure out what is going on with this?

donquixote’s picture

You could continue debugging this
function _menu_editor_valid_weight()

and this
http://api.drupal.org/api/drupal/includes--form.inc/function/drupal_vali...

sakadava’s picture

Neither _menu_editor_valid_weight() nor drupal_validate_form() are called.

I looked further up in drupal_process_form(), specifically the test immediately after the call to form_builder():

if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {

$form_id is set to menu_editor_overview_form.

The POST trace shows the form_id as menu_editor_overview_form.

$form['#post']['form_id'] doesn't look like it's set at this point. The test fails and drupal_process_form() exits without doing any work.

If you have any suggestions where to look now I'd appreciate it.

donquixote’s picture

Weird. Is this if() statement where it fails?

What about #programmed?
You could dpm($form), to look into the values of #programmed and #post.
(needs devel.module installed)

Sorry if we can only do this in little steps ..

sakadava’s picture

FileSize
18.35 KB

No need for apology about little steps. I am extremely happy to be getting your help on this and have no complaints about the time it's taking.

Yes I think it's the if that's failing.

I tried dpm($form) but ran out of memory so I placed a dpm() for each variable used in the if statement.

i.e.

  dpm($form['#programmed']);
  dpm($form['#post']);
  dpm($form['#post']['form_id']);
  dpm($form_id);
  
  if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {

I've attached the resultant output, just in case I misinterpreted it but in essence it looks to me as though:
#programmed is empty
$form['#post']['form_id'] is empty

As before I appreciate any further guidance on debugging this.

donquixote’s picture

Two quick hints for better debugging:

http://www.thingy-ma-jig.co.uk/blog/02-10-2007/hugely-useful-hugely-undo...
dvm() is nice to show what kind of empty we are dealing with: Empty string, NULL, FALSE, etc.

And in some cases I do things like

dpm("form['#post']:");
dpm($form['#post']);

to better know which output is coming from which dpm().

Or, if I know already it's a string:
dpm("form id: ($form_id)");

That said, I think your output is understandable without the above tricks.
So, assuming the $form['#post']['form_id'] is empty, that looks weird to me. Does the same happen on other menus?

sakadava’s picture

FileSize
36.13 KB

Thanks for the debugging tips - aside from solving the actual problem this is an extremely useful task for me to get deeper insight into the debugging process and to learn more.

With the menu that doesn't work properly:

form['#programmed'] is bool(false)
form['#post']['form_id'] is NULL

With the menu that works properly, it looks like drupal_process_form() is called twice for the menu_editor_overview_form:

First time:

form['#programmed'] is bool(false)
form['#post']['form_id'] is "menu_editor_overview_form'

And again for the second time:

form['#programmed'] is bool(false)
form['#post']['form_id'] is "menu_editor_overview_form'

Attached is the screen output if this helps.

So it looks like the if is failing because of the form['#post']['form_id'] being set to NULL.

Please let me know know if you have any suggestions of where to take the debugging next.

sakadava’s picture

After some more investigation it seems this issue may be related to the number of items in the menu, or possibly the size of the data posted when the form is submitted.

I have been able to reproduce the issue on other menus by increasing the number of menu items beyond a particular threshold, whereupon Menu Editor stops working. Then by using the standard menu editor, I can reduce the number of menu items and Menu Editor starts working again.

So I don't know whether this issue is specifically related to Menu Editor, or instead it is more generic. Maybe I'm just hitting it with Menu Editor due to the volume of data it uses?

The menus in question aren't particularly huge with about 120 items. I can't see anything particularly peculiar about the server set up (although I believe PHP 5.3.3 has caused some problems).

I will see what else I can turn up but if there are any pointers for where to continue my investigation I'd appreciate it.

donquixote’s picture

What about PHP's post_max_size setting?
http://php.net/manual/de/ini.core.php

sakadava’s picture

post_max_size is reportedly set to 60M but now I'm not convinced this true given what's happening. Perhaps this is starting to look more like a server issue and possibly nothing to do with Menu Editor per se.

The size of the post data reported by HttpFox is about 28k and I'm surprised that such a small server limit exists - I would have thought I'd have bumped into this before. In any case I will investigate further and report back. As before any guidance gratefully accepted.

donquixote’s picture

You could debug the index.php and look into $_POST before anything else.
If don't want a var_dump or print_r to break your html, you could store the $_POST in a global var and dpm() it some time later.

In index.php:

<?php
$original_post = $_POST;
[...]
?>

In drupal_process_form():

<?php
  dpm("Original post values:");
  dpm($GLOBALS['original_post']);
  dpm("Current post values:");
  dpm($_POST);
  dpm("Form post values:");
  dpm($form['#post']);
  dpm("Form #programmed, #post/form_id, form_id");
  dpm($form['#programmed']);
  dpm($form['#post']['form_id']);
  dpm($form_id);
?>

Obviously you want to find out if something is missing in the original post values, or otherwise if it gets lost on the way.

sakadava’s picture

And just to reinforce that this could be a server issue, I've run the site on a different server and the Menu Editor works correctly. As before, I will investigate server configuration and report back.

sakadava’s picture

The Apache server was recompiled without Suhosin support and this issue could not be reproduced. So this looks like Suhosin was the cause of this problem. Menu Editor on certain menus generated excessive post fields for this particular server configuration.

Thank you for your help with this donquixote. I appreciate your prompt and informative responses and learnt a lot from them. I hope you didn't spend too much time on this, given it wasn't actually a Menu Editor issue.

donquixote’s picture

Status: Active » Closed (cannot reproduce)

I guess I can close this now.

I hope you didn't spend too much time on this, given it wasn't actually a Menu Editor issue.

I am obsessed with keeping a zero bug count for this module :)
(except for "postponed / needs more info" issues)

schan23’s picture

I had the same issue. However, this doesn't seem to be module issue.

For all those who run into the same issue, try increasing value of your max_input_vars variable in your php configuration. The default value of this variable is 1000. For large menus this value should be more than 1000.

donquixote’s picture

I'd say, if this is the reason, then we should try to properly display an error message.
Anyone wanna do a patch?

jstoller’s picture

Version: 6.x-2.2 » 7.x-1.x-dev
Priority: Normal » Major
Issue summary: View changes
Status: Closed (cannot reproduce) » Active

I just came across this error in the D7 version (in the middle of a meeting, of course). The lack of any error when the form was submitted was particularly disconcerting. It looks like setting max_input_vars to 2000 in my php configuration did fix it.

donquixote’s picture

I get the idea that the Drupal form builder should generally and always check max_input_vars (and maybe post_max_size?), and compare this to the number of fields in the current form. And maybe do some better error management in case this limit is exceeded.

Another idea would be to redesign the form so that fewer fields are submitted. E.g. some javascript magic to only submit those fields that have changed. Or to combined different fields into one json text field. Or pagination, so that not all links are visible at once.

Maybe first we should confirm that the problem is actually too long menus blowing up limits in the php configuration, and make it reproducible.
This could be done by creating feature modules which define really big menus, and see how big they need to be to blow up the form.

This all sounds like a lot of work, so I appreciate any help.

jstoller’s picture

Adding a related core issue.

jstoller’s picture

donquixote’s picture

@jstoller: I assume that the core admin/structure/menu/manage/% needs a bigger menu to blow up, since it has fewer form elements per menu item. Would be great if we can reproduce this.

sakadava’s picture

This issue continues to affect me on larger sites and my first step now when I run into anything suspiciously like this is to go sort out max_input_vars (although originally for me max_input_vars wasn't the culprit, rather it was Suhosin).

The problem isn't to do with menus per se, although Power Edit will tend to hit the issue frequently because it increases the number of form elements for the menu. I originally encountered the issue with Power Edit but have subsequently run into it on the permissions form which can also get very large.

So I don't think we need anything too complicated to reproduce this - just generate enough input fields to exceed max_input_vars.

I created a little module which does reproduce the issue on demand - it just gets the value of max_input_vars then creates sufficient input fields to ensure the issue occurs.

What's the 'authorised' way to share this little debug module with you? For example I could just tar it up and attach it as a file.

sakadava’s picture

Alternatively we can just use my server - I set up a test environment where we could play with this. I can share the details with you privately if you'd like to give it a whirl. I'm also keen to get involved further - this was one of my earliest 'meaty' issues since getting involved with Drupal and it will be good to work with you again.

donquixote’s picture

@sakadava: Tarball/zip is fine, or a repo on github.

sakadava’s picture

FileSize
1.42 KB

Attached as a zip file.

Just enable the module as usual and visit www.example.com/max_vars_form. The module gets the value of max_input_vars and creates that many checkboxes. If you uncheck some of the checkboxes the form will get validated and submitted, in which case it will generate messages telling you the relevant function has been reached. If all the checkboxes are checked you ought not see the messages indicating the problem has been reproduced

Hope this helps and let me know if I can assist in any other way and let me know how you get on.

socratesone’s picture

Just in case anyone wants a quick way to tell how many actual input variables are being submitted, you can open up the firebug console and put this in there:

$count = 0;

jQuery('input').each(function(){
  
   $count++;  
  
});

alert($count);

Should at least tell you what you need to set max_input_vars to.

jenlampton’s picture

Issue tags: +max_input_vars

tagging

donquixote’s picture

Title: Menu not changed, no error message displayed » Menu not changed, no error message displayed (max_input_vars)
donquixote’s picture

If max_input_vars or another php limit on POST data is the problem, I have an idea.
I think this is not limited to menu_editor, but could theoretically happen on any form in Drupal.

So, what about a separate contrib module that:
- uses hook_form_alter() to add a hidden element at the end of every (*) form, (marked as #required), pre-filled with '1'.
- registers a js/jquery behavior on submit, that creates a new hidden element at the beginning of the form, with all the form data encoded as json.

(*) There could be a way to enable this for specific forms only, e.g. with a special property key.

In the PHP request that handles the submit:
- check the form values for the two hidden elements.
- if both are empty, fail validation with "the form data was too big, and it seems js was disabled."
- elseif the first is empty, use the regular form values.
- elseif the second is empty, use the json form values (copy them into the POST array).
- else, compare the json value with the POST values, fail validation if they don't match.

Why would this work?
The hidden element at the end of the form will be empty if the form data was too big.

donquixote’s picture

donquixote’s picture

Status: Active » Closed (duplicate)