Pull merge.
[yaffs-website] / web / core / lib / Drupal / Core / Form / FormSubmitter.php
1 <?php
2
3 namespace Drupal\Core\Form;
4
5 use Drupal\Core\Url;
6 use Symfony\Component\HttpFoundation\RedirectResponse;
7 use Symfony\Component\HttpFoundation\RequestStack;
8 use Symfony\Component\HttpFoundation\Response;
9 use Drupal\Core\Routing\UrlGeneratorInterface;
10
11 /**
12  * Provides submission processing for forms.
13  */
14 class FormSubmitter implements FormSubmitterInterface {
15
16   /**
17    * The URL generator.
18    *
19    * @var \Drupal\Core\Routing\UrlGeneratorInterface
20    */
21   protected $urlGenerator;
22
23   /**
24    * The request stack.
25    *
26    * @var \Symfony\Component\HttpFoundation\RequestStack
27    */
28   protected $requestStack;
29
30   /**
31    * Constructs a new FormValidator.
32    *
33    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
34    *   The request stack.
35    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
36    */
37   public function __construct(RequestStack $request_stack, UrlGeneratorInterface $url_generator) {
38     $this->requestStack = $request_stack;
39     $this->urlGenerator = $url_generator;
40   }
41
42   /**
43    * {@inheritdoc}
44    */
45   public function doSubmitForm(&$form, FormStateInterface &$form_state) {
46     if (!$form_state->isSubmitted()) {
47       return;
48     }
49
50     // Execute form submit handlers.
51     $this->executeSubmitHandlers($form, $form_state);
52
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;
60
61       $batch['progressive'] = !$form_state->isProgrammed();
62       $response = batch_process();
63       if ($batch['progressive']) {
64         return $response;
65       }
66
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.
71     }
72
73     // Set a flag to indicate the form has been processed and executed.
74     $form_state->setExecuted();
75
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);
79     }
80
81     // If there is a response was set, return it instead of continuing.
82     if (($response = $form_state->getResponse()) && $response instanceof Response) {
83       return $response;
84     }
85   }
86
87   /**
88    * {@inheritdoc}
89    */
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'];
96     }
97
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;
109       }
110       else {
111         call_user_func_array($form_state->prepareCallback($callback), [&$form, &$form_state]);
112       }
113     }
114   }
115
116   /**
117    * {@inheritdoc}
118    */
119   public function redirectForm(FormStateInterface $form_state) {
120     $redirect = $form_state->getRedirect();
121
122     // Allow using redirect responses directly if needed.
123     if ($redirect instanceof RedirectResponse) {
124       return $redirect;
125     }
126
127     $url = NULL;
128     // Check for a route-based redirection.
129     if ($redirect instanceof Url) {
130       $url = $redirect->setAbsolute()->toString();
131     }
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]);
136     }
137
138     if ($url) {
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);
143     }
144   }
145
146   /**
147    * Wraps drupal_installation_attempted().
148    *
149    * @return bool
150    */
151   protected function drupalInstallationAttempted() {
152     return drupal_installation_attempted();
153   }
154
155   /**
156    * Wraps batch_get().
157    */
158   protected function &batchGet() {
159     return batch_get();
160   }
161
162 }