3 namespace Drupal\Core\Form;
6 use Symfony\Component\HttpFoundation\RedirectResponse;
7 use Symfony\Component\HttpFoundation\RequestStack;
8 use Symfony\Component\HttpFoundation\Response;
9 use Drupal\Core\Routing\UrlGeneratorInterface;
12 * Provides submission processing for forms.
14 class FormSubmitter implements FormSubmitterInterface {
19 * @var \Drupal\Core\Routing\UrlGeneratorInterface
21 protected $urlGenerator;
26 * @var \Symfony\Component\HttpFoundation\RequestStack
28 protected $requestStack;
31 * Constructs a new FormValidator.
33 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
35 * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
37 public function __construct(RequestStack $request_stack, UrlGeneratorInterface $url_generator) {
38 $this->requestStack = $request_stack;
39 $this->urlGenerator = $url_generator;
45 public function doSubmitForm(&$form, FormStateInterface &$form_state) {
46 if (!$form_state->isSubmitted()) {
50 // Execute form submit handlers.
51 $this->executeSubmitHandlers($form, $form_state);
53 // If batches were set in the submit handlers, we process them now,
54 // possibly ending execution. We make sure we do not react to the batch
55 // that is already being processed (if a batch operation performs a
56 // \Drupal\Core\Form\FormBuilderInterface::submitForm).
57 if ($batch = &$this->batchGet() && !isset($batch['current_set'])) {
58 // Store $form_state information in the batch definition.
59 $batch['form_state'] = $form_state;
61 $batch['progressive'] = !$form_state->isProgrammed();
62 $response = batch_process();
63 if ($batch['progressive']) {
67 // Execution continues only for programmatic forms.
68 // For 'regular' forms, we get redirected to the batch processing
69 // page. Form redirection will be handled in _batch_finished(),
70 // after the batch is processed.
73 // Set a flag to indicate the form has been processed and executed.
74 $form_state->setExecuted();
76 // If no response has been set, process the form redirect.
77 if (!$form_state->getResponse() && $redirect = $this->redirectForm($form_state)) {
78 $form_state->setResponse($redirect);
81 // If there is a response was set, return it instead of continuing.
82 if (($response = $form_state->getResponse()) && $response instanceof Response) {
90 public function executeSubmitHandlers(&$form, FormStateInterface &$form_state) {
91 // If there was a button pressed, use its handlers.
92 $handlers = $form_state->getSubmitHandlers();
93 // Otherwise, check for a form-level handler.
94 if (!$handlers && !empty($form['#submit'])) {
95 $handlers = $form['#submit'];
98 foreach ($handlers as $callback) {
99 // Check if a previous _submit handler has set a batch, but make sure we
100 // do not react to a batch that is already being processed (for instance
101 // if a batch operation performs a
102 // \Drupal\Core\Form\FormBuilderInterface::submitForm()).
103 if (($batch = &$this->batchGet()) && !isset($batch['id'])) {
104 // Some previous submit handler has set a batch. To ensure correct
105 // execution order, store the call in a special 'control' batch set.
106 // See _batch_next_set().
107 $batch['sets'][] = ['form_submit' => $callback];
108 $batch['has_form_submits'] = TRUE;
111 call_user_func_array($form_state->prepareCallback($callback), [&$form, &$form_state]);
119 public function redirectForm(FormStateInterface $form_state) {
120 $redirect = $form_state->getRedirect();
122 // Allow using redirect responses directly if needed.
123 if ($redirect instanceof RedirectResponse) {
128 // Check for a route-based redirection.
129 if ($redirect instanceof Url) {
130 $url = $redirect->setAbsolute()->toString();
132 // If no redirect was specified, redirect to the current path.
133 elseif ($redirect === NULL) {
134 $request = $this->requestStack->getCurrentRequest();
135 $url = $this->urlGenerator->generateFromRoute('<current>', [], ['query' => $request->query->all(), 'absolute' => TRUE]);
139 // According to RFC 7231, 303 See Other status code must be used to redirect
140 // user agent (and not default 302 Found).
141 // @see http://tools.ietf.org/html/rfc7231#section-6.4.4
142 return new RedirectResponse($url, Response::HTTP_SEE_OTHER);
147 * Wraps drupal_installation_attempted().
151 protected function drupalInstallationAttempted() {
152 return drupal_installation_attempted();
158 protected function &batchGet() {