Form alter allows modules to make additions to forms.
Form alter could also change the structure of a form, which may be required by some module in some context, e.g. node type.
However, a module cannot change the structure of a form, really, until all the form components have been added.
Modules are called to alter a form in a sequence that is either defined alphabetically or by the order modules were enabled.
As a result, it is beyond the control of any module to make structural changes to a form in such a way that certain preconditions to the change are available at the time of call.
So, there could be 1) a way to set the order, 2) a second api hook to be invoked immediatly after form alter, 3) there can be a schedule determined for a second api hook to be called.
As a good start, choose (2). If case (3) is ever chosen, it should be under the control of an administrator.

Here is some code which may alter a form structure. It a fieldset out of added fieldsets.


function copious_build_store_final_form_alter($form_id, &$form) {
// This is called before form alter and content form alter.

  if ( $form_id == "catalog_node_form" ) {
    $storemoved = array();
    // Alter the form for correct widget appearance.
    foreach ( $form as $key => $subform ) {
      if ( ( $key != "subtrees" ) && ( $key != "others" ) ) {
        if ( is_array($subform) && ( $key[0] != '#' ) ) {
          if ( isset($subform['#type']) && ($subform['#type'] == 'fieldset') ) {
            $form['others'][$key] = array();
            $storemoved[] = $key;
          }
        }
      }
    }
    foreach ( $storemoved as $key ) {
      $form['others'][$key] = $form[$key];
      unset($form[$key]);
    }
  }
  $key = 'log';
  $form['others'][$key] = $form[$key];
  unset($form[$key]);
}

But, for this to be called, there has to be a small change to form drupal_prepare_form.
Here is code at the bottom of the subroutine:

      *
      *
      *

  foreach (module_implements('form_alter') as $module) {
    $function = $module .'_form_alter';
    $function($form_id, $form);
  }

  foreach (module_implements('final_form_alter') as $module) {
    $function = $module .'_final_form_alter';
    $function($form_id, $form);
  }

  $form = form_builder($form_id, $form);
}


Comments

sun’s picture

Modules are always invoked in the order of their weights. Have a look into the system table to find out the weight of your module and to edit it. For example, Devel module must be invoked last, so it sets its own weight to 88 upon module installation.

yched’s picture

Status: Active » Closed (won't fix)

I think this is a won't fix - adding hooks after hooks is not the right way, for there will always be needs for adding stuff after that second level...

I think there is code in chx's sandbox for 'per hook' weights, waiting for someone to pick up...