Subsequent submit callbacks are handled incorrectly after batch is added

Created on 17 May 2016, over 8 years ago
Updated 6 August 2024, 5 months ago

The problem

In \Drupal\Core\Form\FormSubmitter::executeSubmitHandlers(), there is the following code for calling all submit callbacks and handling batches appropriately (by queuing all further submit callbacks until after the batch has been executed):

    foreach ($handlers as $callback) {
      // Check if a previous _submit handler has set a batch, but make sure we
      // do not react to a batch that is already being processed (for instance
      // if a batch operation performs a
      //  \Drupal\Core\Form\FormBuilderInterface::submitForm()).
      if (($batch = &$this->batchGet()) && !isset($batch['id'])) {
        // Some previous submit handler has set a batch. To ensure correct
        // execution order, store the call in a special 'control' batch set.
        // See _batch_next_set().
        $batch['sets'][] = array('form_submit' => $callback);
        $batch['has_form_submits'] = TRUE;
      }
      else {
        call_user_func_array($form_state->prepareCallback($callback), array(&$form, &$form_state));
      }
    }

The problem: the $callback added to the batch sets if a batch was set doesn't have the necessary $form_state->prepareCallback() call. Thus, it might just be something like '::save' – which _batch_next_set() won't detect as "callable":

    if (isset($current_set['form_submit']) && ($callback = $current_set['form_submit']) && is_callable($callback)) {
      // We use our stored copies of $form and $form_state to account for
      // possible alterations by previous form submit handlers.
      $complete_form = &$batch['form_state']->getCompleteForm();
      call_user_func_array($callback, array(&$complete_form, &$batch['form_state']));
    }

The effect is, that if this notation is used, all subsequent submit callbacks will just be ignored if one sets a batch.

Suggested solution

Add the necessary $form_state->prepareCallback() call either to \Drupal\Core\Form\FormSubmitter::executeSubmitHandlers() (probably the better idea) or to _batch_next_set() (should work just as well, but would appear a bit stranger, in my opinion).

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
FormΒ  β†’

Last updated 1 day ago

Created by

πŸ‡¦πŸ‡ΉAustria drunken monkey Vienna, Austria

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024