FormSubmitter.php

Same filename in other branches
  1. 9 core/lib/Drupal/Core/Form/FormSubmitter.php
  2. 8.9.x core/lib/Drupal/Core/Form/FormSubmitter.php
  3. 11.x core/lib/Drupal/Core/Form/FormSubmitter.php

Namespace

Drupal\Core\Form

File

core/lib/Drupal/Core/Form/FormSubmitter.php

View source
<?php

namespace Drupal\Core\Form;

use Drupal\Core\EventSubscriber\RedirectResponseSubscriber;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Routing\UrlGeneratorInterface;

/**
 * Provides submission processing for forms.
 */
class FormSubmitter implements FormSubmitterInterface {
    
    /**
     * The URL generator.
     *
     * @var \Drupal\Core\Routing\UrlGeneratorInterface
     */
    protected $urlGenerator;
    
    /**
     * The request stack.
     *
     * @var \Symfony\Component\HttpFoundation\RequestStack
     */
    protected $requestStack;
    
    /**
     * The redirect response subscriber.
     *
     * @var \Drupal\Core\EventSubscriber\RedirectResponseSubscriber
     */
    protected RedirectResponseSubscriber $redirectResponseSubscriber;
    
    /**
     * Constructs a new FormSubmitter.
     *
     * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
     *   The request stack.
     * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
     *   The URL generator.
     * @param \Drupal\Core\EventSubscriber\RedirectResponseSubscriber|null $redirect_response_subscriber
     *   The redirect response subscriber.
     */
    public function __construct(RequestStack $request_stack, UrlGeneratorInterface $url_generator, ?RedirectResponseSubscriber $redirect_response_subscriber = NULL) {
        $this->requestStack = $request_stack;
        $this->urlGenerator = $url_generator;
        if (is_null($redirect_response_subscriber)) {
            @trigger_error('Calling ' . __CLASS__ . '::__construct() without the $redirect_response_subscriber argument is deprecated in drupal:10.2.0 and is required in drupal:11.0.0. See https://www.drupal.org/node/3377297', E_USER_DEPRECATED);
            $redirect_response_subscriber = \Drupal::service('redirect_response_subscriber');
        }
        $this->redirectResponseSubscriber = $redirect_response_subscriber;
    }
    
    /**
     * {@inheritdoc}
     */
    public function doSubmitForm(&$form, FormStateInterface &$form_state) {
        if (!$form_state->isSubmitted()) {
            return;
        }
        // Execute form submit handlers.
        $this->executeSubmitHandlers($form, $form_state);
        // If batches were set in the submit handlers, we process them now,
        // possibly ending execution. We make sure we do not react to the batch
        // that is already being processed (if a batch operation performs a
        // \Drupal\Core\Form\FormBuilderInterface::submitForm).
        if (($batch =& $this->batchGet()) && !isset($batch['current_set'])) {
            // Store $form_state information in the batch definition.
            $batch['form_state'] = $form_state;
            $batch['progressive'] = !$form_state->isProgrammed();
            $response = batch_process();
            // If the batch has been completed and _batch_finished() called then
            // $batch will be NULL.
            if ($batch && $batch['progressive']) {
                return $response;
            }
            // Execution continues only for programmatic forms.
            // For 'regular' forms, we get redirected to the batch processing
            // page. Form redirection will be handled in _batch_finished(),
            // after the batch is processed.
        }
        // Set a flag to indicate the form has been processed and executed.
        $form_state->setExecuted();
        // If no response has been set, process the form redirect.
        if (!$form_state->getResponse() && ($redirect = $this->redirectForm($form_state))) {
            $form_state->setResponse($redirect);
        }
        // If there is a response was set, return it instead of continuing.
        if (($response = $form_state->getResponse()) && $response instanceof Response) {
            return $response;
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function executeSubmitHandlers(&$form, FormStateInterface &$form_state) {
        // If there was a button pressed, use its handlers.
        $handlers = $form_state->getSubmitHandlers();
        // Otherwise, check for a form-level handler.
        if (!$handlers && !empty($form['#submit'])) {
            $handlers = $form['#submit'];
        }
        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'][] = [
                    'form_submit' => $callback,
                ];
                $batch['has_form_submits'] = TRUE;
            }
            else {
                call_user_func_array($form_state->prepareCallback($callback), [
                    &$form,
                    &$form_state,
                ]);
            }
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function redirectForm(FormStateInterface $form_state) {
        $redirect = $form_state->getRedirect();
        $this->redirectResponseSubscriber
            ->setIgnoreDestination($form_state->getIgnoreDestination());
        // Allow using redirect responses directly if needed.
        if ($redirect instanceof RedirectResponse) {
            return $redirect;
        }
        $url = NULL;
        // Check for a route-based redirection.
        if ($redirect instanceof Url) {
            $url = $redirect->setAbsolute()
                ->toString();
        }
        elseif ($redirect === NULL) {
            $request = $this->requestStack
                ->getCurrentRequest();
            $url = $this->urlGenerator
                ->generateFromRoute('<current>', [], [
                'query' => $request->query
                    ->all(),
                'absolute' => TRUE,
            ]);
        }
        if ($url) {
            // According to RFC 7231, 303 See Other status code must be used to redirect
            // user agent (and not default 302 Found).
            // @see http://tools.ietf.org/html/rfc7231#section-6.4.4
            return new RedirectResponse($url, Response::HTTP_SEE_OTHER);
        }
    }
    
    /**
     * Wraps batch_get().
     */
    protected function &batchGet() {
        return batch_get();
    }

}

Classes

Title Deprecated Summary
FormSubmitter Provides submission processing for forms.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.