I'd like to customize the update.php form. Theoretically, every form presented by drupal should be customizable via hook_form_alter. In the case of update.php, the form can be modified, but the submit behavior cannot.

To modify the form, implement hook_form_alter() in custom_module.install. (NB: custom_module.install, not custom_module.module). Normally, in hook_form_alter one can overwrite or append $form['#submit'] to control the behavior on submit. However, in update.php, the #submit values are ignored.

The reason for this is that in update.php, the form is created (via drupal_get_form()) only on one page. drupal_get_form() is not called after the form is submitted, and that is normally where the form API would work it's #submit magic.

So, my first attempt to fix this issue was to add a call to add a call

drupal_get_form('update_script_selection_form');

Near the top of update_update_page(). This failed to do the trick, however. I don't know the form API inside out, but it appears to perform a redirect after calling the #submit callbacks. I'm not sure whether that can be avoided, but it prevents the rest of the update script from doing its job. So it's impossible to use the #submit method to affect how the update script behaves. It's also impossible to use $_POST in one of my hook_update_N functions, because the nifty javascript update bar makes everything more complicated. By the time the hook_update_N is called, the original form values are long forgotten.

I'd like to see the update.php script use the normal form api methods to do it's work, allowing third-party modules to customize the behavior. Failing that, I'd like to see the original $_POST values written to the $_SESSION, so that hook_update_N() could find out what they were.

Thanks for any help.

CommentFileSizeAuthor
#2 123702.patch820 bytesDave Cohen
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Steven’s picture

Status: Active » Postponed (maintainer needs more info)

Updating should remain a simple process, both for the end user and in code (some features may not work because the DB is not up to date). IMO form_alter is not suitable for update.php, and the fact that this works at all is purely an accident.

An update that needs a UI sounds like a bad idea. The purpose of an update is to transform the old content into the new data format. If you added, changed or removed features, you should map to the closest available construct. What sort of things would you add to the updating form?

If you need more than trivial operations to update the old data, consider making a "foo_updater.module" or stand-alone script.

By the way, update.php is not complicated because of the 'nifty javascript bar', but because updates are spread over multiple requests to avoid PHP time and memory limits. Updates can be run multiple times if they report that they had not finished 100%. The JavaScript is purely presentational, and the updater works fine with JS turned off. But it will use multiple requests in both cases.

Dave Cohen’s picture

Status: Postponed (maintainer needs more info) » Needs review
FileSize
820 bytes

Thanks for the explanation of why the updates are spread across multiple requests. I thought that was just to make the progress bar move.

I'm still of the opinion that update.php should use the form API to its full advantage, and let 3rd party module customize to their hearts content. We may agree to disagree on that.

For my development, I create (at least) two copies of a site I'm working on. One I call the base, the other the sandbox. During development, I adjust settings and add content to the sandbox all I want. But to the base site I make only changes that will go into the final version. I make a special dump of the base database, which can be imported into the sandbox database so that changes made to the base move upstream to all the sandboxes out there. This way I can careful control which changes get made to my demo and production sites (only changes made to base, not my sandbox). I wrote this up a long time ago http://www.dave-cohen.com/node/1066, and have recently updated that code to Drupal 5.

I don't know how clear that explanation is. The point is that during update.php I want to import a sql file. The sql uses 'INSERT IGNORE' for most queries, so that changes made to any of the 'sandboxes' do not get overwritten willy-nilly. But sometimes I want to force changes. For example making sure the input formats end up reflecting exactly what's in the SQL dump by doing a "DELETE FROM {filters}" and "DELETE FROM {filter_formats}" before importing the SQL. To control that behavior, I'd like to add a checkbox to update.php.

The attached patch works for me. I hope it is considered for submission.

Off topic: Everyone should take care when using the "active (needs more info)" status. It makes the issue disappear from virtually every page on drupal.org. Even I, the submitter, no longer see it on "my issues" page. It's basically a way of burying an issue so that it is never found again. Personally I think it should be done away with.

chx’s picture

Status: Needs review » Closed (won't fix)

update.php does a full bootstrap, so all the modules are in place. modules implementing hook_form_alter do check form_id and they should be cautious about what they do if its the update form (because the DB is in a strange state at this moment). The question is, is there something that does NOT depend on form_id? And the answer is hook_elements. This is a won't fix because if you happen to implement hook_elements adding a #process or something to some field (like many do to textarea) then you need to be cautious about the state of the database and this is quite hard, and might cause extremely strange, hard to find the cause bugs.