Security update for Core, with self-updated composer
[yaffs-website] / web / core / lib / Drupal / Core / Form / FormBuilder.php
1 <?php
2
3 namespace Drupal\Core\Form;
4
5 use Drupal\Component\Utility\Crypt;
6 use Drupal\Component\Utility\Html;
7 use Drupal\Component\Utility\NestedArray;
8 use Drupal\Component\Utility\UrlHelper;
9 use Drupal\Core\Access\AccessResultInterface;
10 use Drupal\Core\Access\CsrfTokenGenerator;
11 use Drupal\Core\DependencyInjection\ClassResolverInterface;
12 use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
13 use Drupal\Core\Extension\ModuleHandlerInterface;
14 use Drupal\Core\Form\Exception\BrokenPostRequestException;
15 use Drupal\Core\Render\Element;
16 use Drupal\Core\Render\ElementInfoManagerInterface;
17 use Drupal\Core\Theme\ThemeManagerInterface;
18 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
19 use Symfony\Component\HttpFoundation\FileBag;
20 use Symfony\Component\HttpFoundation\RequestStack;
21 use Symfony\Component\HttpFoundation\Response;
22
23 /**
24  * Provides form building and processing.
25  *
26  * @ingroup form_api
27  */
28 class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormSubmitterInterface, FormCacheInterface {
29
30   /**
31    * The module handler.
32    *
33    * @var \Drupal\Core\Extension\ModuleHandlerInterface
34    */
35   protected $moduleHandler;
36
37   /**
38    * The event dispatcher.
39    *
40    * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
41    */
42   protected $eventDispatcher;
43
44   /**
45    * The request stack.
46    *
47    * @var \Symfony\Component\HttpFoundation\RequestStack
48    */
49   protected $requestStack;
50
51   /**
52    * The element info manager.
53    *
54    * @var \Drupal\Core\Render\ElementInfoManagerInterface
55    */
56   protected $elementInfo;
57
58   /**
59    * The CSRF token generator to validate the form token.
60    *
61    * @var \Drupal\Core\Access\CsrfTokenGenerator
62    */
63   protected $csrfToken;
64
65   /**
66    * The class resolver.
67    *
68    * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
69    */
70   protected $classResolver;
71
72   /**
73    * The current user.
74    *
75    * @var \Drupal\Core\Session\AccountInterface
76    */
77   protected $currentUser;
78
79   /**
80    * The theme manager.
81    *
82    * @var \Drupal\Core\Theme\ThemeManagerInterface
83    */
84   protected $themeManager;
85
86   /**
87    * @var \Drupal\Core\Form\FormValidatorInterface
88    */
89   protected $formValidator;
90
91   /**
92    * @var \Drupal\Core\Form\FormSubmitterInterface
93    */
94   protected $formSubmitter;
95
96   /**
97    * The form cache.
98    *
99    * @var \Drupal\Core\Form\FormCacheInterface
100    */
101   protected $formCache;
102
103   /**
104    * Defines element value callables which are safe to run even when the form
105    * state has an invalid CSRF token.
106    *
107    * Excluded from this list on purpose:
108    *  - Drupal\file\Element\ManagedFile::valueCallback
109    *  - Drupal\Core\Datetime\Element\Datelist::valueCallback
110    *  - Drupal\Core\Datetime\Element\Datetime::valueCallback
111    *  - Drupal\Core\Render\Element\ImageButton::valueCallback
112    *  - Drupal\file\Plugin\Field\FieldWidget\FileWidget::value
113    *  - color_palette_color_value
114    *
115    * @var array
116    */
117   protected $safeCoreValueCallables = [
118     'Drupal\Core\Render\Element\Checkbox::valueCallback',
119     'Drupal\Core\Render\Element\Checkboxes::valueCallback',
120     'Drupal\Core\Render\Element\Email::valueCallback',
121     'Drupal\Core\Render\Element\FormElement::valueCallback',
122     'Drupal\Core\Render\Element\MachineName::valueCallback',
123     'Drupal\Core\Render\Element\Number::valueCallback',
124     'Drupal\Core\Render\Element\PathElement::valueCallback',
125     'Drupal\Core\Render\Element\Password::valueCallback',
126     'Drupal\Core\Render\Element\PasswordConfirm::valueCallback',
127     'Drupal\Core\Render\Element\Radio::valueCallback',
128     'Drupal\Core\Render\Element\Radios::valueCallback',
129     'Drupal\Core\Render\Element\Range::valueCallback',
130     'Drupal\Core\Render\Element\Search::valueCallback',
131     'Drupal\Core\Render\Element\Select::valueCallback',
132     'Drupal\Core\Render\Element\Tableselect::valueCallback',
133     'Drupal\Core\Render\Element\Table::valueCallback',
134     'Drupal\Core\Render\Element\Tel::valueCallback',
135     'Drupal\Core\Render\Element\Textarea::valueCallback',
136     'Drupal\Core\Render\Element\Textfield::valueCallback',
137     'Drupal\Core\Render\Element\Token::valueCallback',
138     'Drupal\Core\Render\Element\Url::valueCallback',
139     'Drupal\Core\Render\Element\Weight::valueCallback',
140   ];
141
142   /**
143    * Constructs a new FormBuilder.
144    *
145    * @param \Drupal\Core\Form\FormValidatorInterface $form_validator
146    *   The form validator.
147    * @param \Drupal\Core\Form\FormSubmitterInterface $form_submitter
148    *   The form submission processor.
149    * @param \Drupal\Core\Form\FormCacheInterface $form_cache
150    *   The form cache.
151    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
152    *   The module handler.
153    * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
154    *   The event dispatcher.
155    * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
156    *   The request stack.
157    * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
158    *   The class resolver.
159    * @param \Drupal\Core\Render\ElementInfoManagerInterface $element_info
160    *   The element info manager.
161    * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
162    *   The theme manager.
163    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
164    *   The CSRF token generator.
165    */
166   public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, FormCacheInterface $form_cache, ModuleHandlerInterface $module_handler, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, ClassResolverInterface $class_resolver, ElementInfoManagerInterface $element_info, ThemeManagerInterface $theme_manager, CsrfTokenGenerator $csrf_token = NULL) {
167     $this->formValidator = $form_validator;
168     $this->formSubmitter = $form_submitter;
169     $this->formCache = $form_cache;
170     $this->moduleHandler = $module_handler;
171     $this->eventDispatcher = $event_dispatcher;
172     $this->requestStack = $request_stack;
173     $this->classResolver = $class_resolver;
174     $this->elementInfo = $element_info;
175     $this->csrfToken = $csrf_token;
176     $this->themeManager = $theme_manager;
177   }
178
179   /**
180    * {@inheritdoc}
181    */
182   public function getFormId($form_arg, FormStateInterface &$form_state) {
183     // If the $form_arg is the name of a class, instantiate it. Don't allow
184     // arbitrary strings to be passed to the class resolver.
185     if (is_string($form_arg) && class_exists($form_arg)) {
186       $form_arg = $this->classResolver->getInstanceFromDefinition($form_arg);
187     }
188
189     if (!is_object($form_arg) || !($form_arg instanceof FormInterface)) {
190       throw new \InvalidArgumentException("The form argument $form_arg is not a valid form.");
191     }
192
193     // Add the $form_arg as the callback object and determine the form ID.
194     $form_state->setFormObject($form_arg);
195     if ($form_arg instanceof BaseFormIdInterface) {
196       $form_state->addBuildInfo('base_form_id', $form_arg->getBaseFormId());
197     }
198     return $form_arg->getFormId();
199   }
200
201   /**
202    * {@inheritdoc}
203    */
204   public function getForm($form_arg) {
205     $form_state = new FormState();
206
207     $args = func_get_args();
208     // Remove $form_arg from the arguments.
209     unset($args[0]);
210     $form_state->addBuildInfo('args', array_values($args));
211
212     return $this->buildForm($form_arg, $form_state);
213   }
214
215   /**
216    * {@inheritdoc}
217    */
218   public function buildForm($form_id, FormStateInterface &$form_state) {
219     // Ensure the form ID is prepared.
220     $form_id = $this->getFormId($form_id, $form_state);
221
222     $request = $this->requestStack->getCurrentRequest();
223
224     // Inform $form_state about the request method that's building it, so that
225     // it can prevent persisting state changes during HTTP methods for which
226     // that is disallowed by HTTP: GET and HEAD.
227     $form_state->setRequestMethod($request->getMethod());
228
229     // Initialize the form's user input. The user input should include only the
230     // input meant to be treated as part of what is submitted to the form, so
231     // we base it on the form's method rather than the request's method. For
232     // example, when someone does a GET request for
233     // /node/add/article?destination=foo, which is a form that expects its
234     // submission method to be POST, the user input during the GET request
235     // should be initialized to empty rather than to ['destination' => 'foo'].
236     $input = $form_state->getUserInput();
237     if (!isset($input)) {
238       $input = $form_state->isMethodType('get') ? $request->query->all() : $request->request->all();
239       $form_state->setUserInput($input);
240     }
241
242     if (isset($_SESSION['batch_form_state'])) {
243       // We've been redirected here after a batch processing. The form has
244       // already been processed, but needs to be rebuilt. See _batch_finished().
245       $form_state = $_SESSION['batch_form_state'];
246       unset($_SESSION['batch_form_state']);
247       return $this->rebuildForm($form_id, $form_state);
248     }
249
250     // If the incoming input contains a form_build_id, we'll check the cache for
251     // a copy of the form in question. If it's there, we don't have to rebuild
252     // the form to proceed. In addition, if there is stored form_state data from
253     // a previous step, we'll retrieve it so it can be passed on to the form
254     // processing code.
255     $check_cache = isset($input['form_id']) && $input['form_id'] == $form_id && !empty($input['form_build_id']);
256     if ($check_cache) {
257       $form = $this->getCache($input['form_build_id'], $form_state);
258     }
259
260     // If the previous bit of code didn't result in a populated $form object, we
261     // are hitting the form for the first time and we need to build it from
262     // scratch.
263     if (!isset($form)) {
264       // If we attempted to serve the form from cache, uncacheable $form_state
265       // keys need to be removed after retrieving and preparing the form, except
266       // any that were already set prior to retrieving the form.
267       if ($check_cache) {
268         $form_state_before_retrieval = clone $form_state;
269       }
270
271       $form = $this->retrieveForm($form_id, $form_state);
272       $this->prepareForm($form_id, $form, $form_state);
273
274       // self::setCache() removes uncacheable $form_state keys (see properties
275       // in \Drupal\Core\Form\FormState) in order for multi-step forms to work
276       // properly. This means that form processing logic for single-step forms
277       // using $form_state->isCached() may depend on data stored in those keys
278       // during self::retrieveForm()/self::prepareForm(), but form processing
279       // should not depend on whether the form is cached or not, so $form_state
280       // is adjusted to match what it would be after a
281       // self::setCache()/self::getCache() sequence. These exceptions are
282       // allowed to survive here:
283       // - always_process: Does not make sense in conjunction with form caching
284       //   in the first place, since passing form_build_id as a GET parameter is
285       //   not desired.
286       // - temporary: Any assigned data is expected to survives within the same
287       //   page request.
288       if ($check_cache) {
289         $cache_form_state = $form_state->getCacheableArray();
290         $cache_form_state['always_process'] = $form_state->getAlwaysProcess();
291         $cache_form_state['temporary'] = $form_state->getTemporary();
292         $form_state = $form_state_before_retrieval;
293         $form_state->setFormState($cache_form_state);
294       }
295     }
296
297     // If this form is an AJAX request, disable all form redirects.
298     $request = $this->requestStack->getCurrentRequest();
299     if ($ajax_form_request = $request->query->has(static::AJAX_FORM_REQUEST)) {
300       $form_state->disableRedirect();
301     }
302
303     // Now that we have a constructed form, process it. This is where:
304     // - Element #process functions get called to further refine $form.
305     // - User input, if any, gets incorporated in the #value property of the
306     //   corresponding elements and into $form_state->getValues().
307     // - Validation and submission handlers are called.
308     // - If this submission is part of a multistep workflow, the form is rebuilt
309     //   to contain the information of the next step.
310     // - If necessary, the form and form state are cached or re-cached, so that
311     //   appropriate information persists to the next page request.
312     // All of the handlers in the pipeline receive $form_state by reference and
313     // can use it to know or update information about the state of the form.
314     $response = $this->processForm($form_id, $form, $form_state);
315
316     // In case the post request exceeds the configured allowed size
317     // (post_max_size), the post request is potentially broken. Add some
318     // protection against that and at the same time have a nice error message.
319     if ($ajax_form_request && !$request->request->has('form_id')) {
320       throw new BrokenPostRequestException($this->getFileUploadMaxSize());
321     }
322
323     // After processing the form, if this is an AJAX form request, interrupt
324     // form rendering and return by throwing an exception that contains the
325     // processed form and form state. This exception will be caught by
326     // \Drupal\Core\Form\EventSubscriber\FormAjaxSubscriber::onException() and
327     // then passed through
328     // \Drupal\Core\Form\FormAjaxResponseBuilderInterface::buildResponse() to
329     // build a proper AJAX response.
330     // Only do this when the form ID matches, since there is no guarantee from
331     // $ajax_form_request that it's an AJAX request for this particular form.
332     if ($ajax_form_request && $form_state->isProcessingInput() && $request->request->get('form_id') == $form_id) {
333       throw new FormAjaxException($form, $form_state);
334     }
335
336     // If the form returns a response, skip subsequent page construction by
337     // throwing an exception.
338     // @see Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
339     //
340     // @todo Exceptions should not be used for code flow control. However, the
341     //   Form API does not integrate with the HTTP Kernel based architecture of
342     //   Drupal 8. In order to resolve this issue properly it is necessary to
343     //   completely separate form submission from rendering.
344     //   @see https://www.drupal.org/node/2367555
345     if ($response instanceof Response) {
346       throw new EnforcedResponseException($response);
347     }
348
349     // If this was a successful submission of a single-step form or the last
350     // step of a multi-step form, then self::processForm() issued a redirect to
351     // another page, or back to this page, but as a new request. Therefore, if
352     // we're here, it means that this is either a form being viewed initially
353     // before any user input, or there was a validation error requiring the form
354     // to be re-displayed, or we're in a multi-step workflow and need to display
355     // the form's next step. In any case, we have what we need in $form, and can
356     // return it for rendering.
357     return $form;
358   }
359
360   /**
361    * {@inheritdoc}
362    */
363   public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL) {
364     $form = $this->retrieveForm($form_id, $form_state);
365
366     // Only GET and POST are valid form methods. If the form receives its input
367     // via POST, then $form_state must be persisted when it is rebuilt between
368     // submissions. If the form receives its input via GET, then persisting
369     // state is forbidden by $form_state->setCached(), and the form must use
370     // the URL itself to transfer its state across steps. Although $form_state
371     // throws an exception based on the request method rather than the form's
372     // method, we base the decision to cache on the form method, because:
373     // - It's the form method that defines what the form needs to do to manage
374     //   its state.
375     // - rebuildForm() should only be called after successful input processing,
376     //   which means the request method matches the form method, and if not,
377     //   there's some other error, so it's ok if an exception is thrown.
378     if ($form_state->isMethodType('POST')) {
379       $form_state->setCached();
380     }
381
382     // If only parts of the form will be returned to the browser (e.g., Ajax or
383     // RIA clients), or if the form already had a new build ID regenerated when
384     // it was retrieved from the form cache, reuse the existing #build_id.
385     // Otherwise, a new #build_id is generated, to not clobber the previous
386     // build's data in the form cache; also allowing the user to go back to an
387     // earlier build, make changes, and re-submit.
388     // @see self::prepareForm()
389     $rebuild_info = $form_state->getRebuildInfo();
390     $enforce_old_build_id = isset($old_form['#build_id']) && !empty($rebuild_info['copy']['#build_id']);
391     $old_form_is_mutable_copy = isset($old_form['#build_id_old']);
392     if ($enforce_old_build_id || $old_form_is_mutable_copy) {
393       $form['#build_id'] = $old_form['#build_id'];
394       if ($old_form_is_mutable_copy) {
395         $form['#build_id_old'] = $old_form['#build_id_old'];
396       }
397     }
398     else {
399       if (isset($old_form['#build_id'])) {
400         $form['#build_id_old'] = $old_form['#build_id'];
401       }
402       $form['#build_id'] = 'form-' . Crypt::randomBytesBase64();
403     }
404
405     // #action defaults to $request->getRequestUri(), but in case of Ajax and
406     // other partial rebuilds, the form is submitted to an alternate URL, and
407     // the original #action needs to be retained.
408     if (isset($old_form['#action']) && !empty($rebuild_info['copy']['#action'])) {
409       $form['#action'] = $old_form['#action'];
410     }
411
412     $this->prepareForm($form_id, $form, $form_state);
413
414     // Caching is normally done in self::processForm(), but what needs to be
415     // cached is the $form structure before it passes through
416     // self::doBuildForm(), so we need to do it here.
417     // @todo For Drupal 8, find a way to avoid this code duplication.
418     if ($form_state->isCached()) {
419       $this->setCache($form['#build_id'], $form, $form_state);
420     }
421
422     // Clear out all group associations as these might be different when
423     // re-rendering the form.
424     $form_state->setGroups([]);
425
426     // Return a fully built form that is ready for rendering.
427     return $this->doBuildForm($form_id, $form, $form_state);
428   }
429
430   /**
431    * {@inheritdoc}
432    */
433   public function getCache($form_build_id, FormStateInterface $form_state) {
434     return $this->formCache->getCache($form_build_id, $form_state);
435   }
436
437   /**
438    * {@inheritdoc}
439    */
440   public function setCache($form_build_id, $form, FormStateInterface $form_state) {
441     $this->formCache->setCache($form_build_id, $form, $form_state);
442   }
443
444   /**
445    * {@inheritdoc}
446    */
447   public function deleteCache($form_build_id) {
448     $this->formCache->deleteCache($form_build_id);
449   }
450
451   /**
452    * {@inheritdoc}
453    */
454   public function submitForm($form_arg, FormStateInterface &$form_state) {
455     $build_info = $form_state->getBuildInfo();
456     if (empty($build_info['args'])) {
457       $args = func_get_args();
458       // Remove $form and $form_state from the arguments.
459       unset($args[0], $args[1]);
460       $form_state->addBuildInfo('args', array_values($args));
461     }
462
463     // Populate FormState::$input with the submitted values before retrieving
464     // the form, to be consistent with what self::buildForm() does for
465     // non-programmatic submissions (form builder functions may expect it to be
466     // there).
467     $form_state->setUserInput($form_state->getValues());
468
469     $form_state->setProgrammed();
470
471     $form_id = $this->getFormId($form_arg, $form_state);
472     $form = $this->retrieveForm($form_id, $form_state);
473     // Programmed forms are always submitted.
474     $form_state->setSubmitted();
475
476     // Reset form validation.
477     $form_state->setValidationEnforced();
478     $form_state->clearErrors();
479
480     $this->prepareForm($form_id, $form, $form_state);
481     $this->processForm($form_id, $form, $form_state);
482   }
483
484   /**
485    * {@inheritdoc}
486    */
487   public function retrieveForm($form_id, FormStateInterface &$form_state) {
488     // Record the $form_id.
489     $form_state->addBuildInfo('form_id', $form_id);
490
491     // We save two copies of the incoming arguments: one for modules to use
492     // when mapping form ids to constructor functions, and another to pass to
493     // the constructor function itself.
494     $build_info = $form_state->getBuildInfo();
495     $args = $build_info['args'];
496
497     $callback = [$form_state->getFormObject(), 'buildForm'];
498
499     $form = [];
500     // Assign a default CSS class name based on $form_id.
501     // This happens here and not in self::prepareForm() in order to allow the
502     // form constructor function to override or remove the default class.
503     $form['#attributes']['class'][] = Html::getClass($form_id);
504     // Same for the base form ID, if any.
505     if (isset($build_info['base_form_id'])) {
506       $form['#attributes']['class'][] = Html::getClass($build_info['base_form_id']);
507     }
508
509     // We need to pass $form_state by reference in order for forms to modify it,
510     // since call_user_func_array() requires that referenced variables are
511     // passed explicitly.
512     $args = array_merge([$form, &$form_state], $args);
513
514     $form = call_user_func_array($callback, $args);
515     // If the form returns a response, skip subsequent page construction by
516     // throwing an exception.
517     // @see Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
518     //
519     // @todo Exceptions should not be used for code flow control. However, the
520     //   Form API currently allows any form builder functions to return a
521     //   response.
522     //   @see https://www.drupal.org/node/2363189
523     if ($form instanceof Response) {
524       throw new EnforcedResponseException($form);
525     }
526     $form['#form_id'] = $form_id;
527
528     return $form;
529   }
530
531   /**
532    * {@inheritdoc}
533    */
534   public function processForm($form_id, &$form, FormStateInterface &$form_state) {
535     $form_state->setValues([]);
536
537     // With GET, these forms are always submitted if requested.
538     if ($form_state->isMethodType('get') && $form_state->getAlwaysProcess()) {
539       $input = $form_state->getUserInput();
540       if (!isset($input['form_build_id'])) {
541         $input['form_build_id'] = $form['#build_id'];
542       }
543       if (!isset($input['form_id'])) {
544         $input['form_id'] = $form_id;
545       }
546       if (!isset($input['form_token']) && isset($form['#token'])) {
547         $input['form_token'] = $this->csrfToken->get($form['#token']);
548       }
549       $form_state->setUserInput($input);
550     }
551
552     // self::doBuildForm() finishes building the form by calling element
553     // #process functions and mapping user input, if any, to #value properties,
554     // and also storing the values in $form_state->getValues(). We need to
555     // retain the unprocessed $form in case it needs to be cached.
556     $unprocessed_form = $form;
557     $form = $this->doBuildForm($form_id, $form, $form_state);
558
559     // Only process the input if we have a correct form submission.
560     if ($form_state->isProcessingInput()) {
561       // Form values for programmed form submissions typically do not include a
562       // value for the submit button. But without a triggering element, a
563       // potentially existing #limit_validation_errors property on the primary
564       // submit button is not taken account. Therefore, check whether there is
565       // exactly one submit button in the form, and if so, automatically use it
566       // as triggering_element.
567       $buttons = $form_state->getButtons();
568       if ($form_state->isProgrammed() && !$form_state->getTriggeringElement() && count($buttons) == 1) {
569         $form_state->setTriggeringElement(reset($buttons));
570       }
571       $this->formValidator->validateForm($form_id, $form, $form_state);
572
573       // \Drupal\Component\Utility\Html::getUniqueId() maintains a cache of
574       // element IDs it has seen, so it can prevent duplicates. We want to be
575       // sure we reset that cache when a form is processed, so scenarios that
576       // result in the form being built behind the scenes and again for the
577       // browser don't increment all the element IDs needlessly.
578       if (!FormState::hasAnyErrors()) {
579         // In case of errors, do not break HTML IDs of other forms.
580         Html::resetSeenIds();
581       }
582
583       // If there are no errors and the form is not rebuilding, submit the form.
584       if (!$form_state->isRebuilding() && !FormState::hasAnyErrors()) {
585         $submit_response = $this->formSubmitter->doSubmitForm($form, $form_state);
586         // If this form was cached, delete it from the cache after submission.
587         if ($form_state->isCached()) {
588           $this->deleteCache($form['#build_id']);
589         }
590         // If the form submission directly returned a response, return it now.
591         if ($submit_response) {
592           return $submit_response;
593         }
594       }
595
596       // Don't rebuild or cache form submissions invoked via self::submitForm().
597       if ($form_state->isProgrammed()) {
598         return;
599       }
600
601       // If $form_state->isRebuilding() has been set and input has been
602       // processed without validation errors, we are in a multi-step workflow
603       // that is not yet complete. A new $form needs to be constructed based on
604       // the changes made to $form_state during this request. Normally, a submit
605       // handler sets $form_state->isRebuilding() if a fully executed form
606       // requires another step. However, for forms that have not been fully
607       // executed (e.g., Ajax submissions triggered by non-buttons), there is no
608       // submit handler to set $form_state->isRebuilding(). It would not make
609       // sense to redisplay the identical form without an error for the user to
610       // correct, so we also rebuild error-free non-executed forms, regardless
611       // of $form_state->isRebuilding().
612       // @todo Simplify this logic; considering Ajax and non-HTML front-ends,
613       //   along with element-level #submit properties, it makes no sense to
614       //   have divergent form execution based on whether the triggering element
615       //   has #executes_submit_callback set to TRUE.
616       if (($form_state->isRebuilding() || !$form_state->isExecuted()) && !FormState::hasAnyErrors()) {
617         // Form building functions (e.g., self::handleInputElement()) may use
618         // $form_state->isRebuilding() to determine if they are running in the
619         // context of a rebuild, so ensure it is set.
620         $form_state->setRebuild();
621         $form = $this->rebuildForm($form_id, $form_state, $form);
622       }
623     }
624
625     // After processing the form, the form builder or a #process callback may
626     // have called $form_state->setCached() to indicate that the form and form
627     // state shall be cached. But the form may only be cached if
628     // $form_state->disableCache() is not called. Only cache $form as it was
629     // prior to self::doBuildForm(), because self::doBuildForm() must run for
630     // each request to accommodate new user input. Rebuilt forms are not cached
631     // here, because self::rebuildForm() already takes care of that.
632     if (!$form_state->isRebuilding() && $form_state->isCached()) {
633       $this->setCache($form['#build_id'], $unprocessed_form, $form_state);
634     }
635   }
636
637   /**
638    * #lazy_builder callback; renders a form action URL.
639    *
640    * @return array
641    *   A renderable array representing the form action.
642    */
643   public function renderPlaceholderFormAction() {
644     return [
645       '#type' => 'markup',
646       '#markup' => $this->buildFormAction(),
647       '#cache' => ['contexts' => ['url.path', 'url.query_args']],
648     ];
649   }
650
651   /**
652    * #lazy_builder callback; renders form CSRF token.
653    *
654    * @param string $placeholder
655    *   A string containing a placeholder, matching the value of the form's
656    *   #token.
657    *
658    * @return array
659    *   A renderable array containing the CSRF token.
660    */
661   public function renderFormTokenPlaceholder($placeholder) {
662     return [
663       '#markup' => $this->csrfToken->get($placeholder),
664       '#cache' => [
665         'contexts' => [
666           'session',
667         ],
668       ],
669     ];
670   }
671
672   /**
673    * {@inheritdoc}
674    */
675   public function prepareForm($form_id, &$form, FormStateInterface &$form_state) {
676     $user = $this->currentUser();
677
678     $form['#type'] = 'form';
679
680     // Only update the action if it is not already set.
681     if (!isset($form['#action'])) {
682       // Instead of setting an actual action URL, we set the placeholder, which
683       // will be replaced at the very last moment. This ensures forms with
684       // dynamically generated action URLs don't have poor cacheability.
685       // Use the proper API to generate the placeholder, when we have one. See
686       // https://www.drupal.org/node/2562341. The placholder uses a fixed string
687       // that is Crypt::hashBase64('Drupal\Core\Form\FormBuilder::prepareForm');
688       $placeholder = 'form_action_p_pvdeGsVG5zNF_XLGPTvYSKCf43t8qZYSwcfZl2uzM';
689
690       $form['#attached']['placeholders'][$placeholder] = [
691         '#lazy_builder' => ['form_builder:renderPlaceholderFormAction', []],
692       ];
693       $form['#action'] = $placeholder;
694     }
695
696     // Fix the form method, if it is 'get' in $form_state, but not in $form.
697     if ($form_state->isMethodType('get') && !isset($form['#method'])) {
698       $form['#method'] = 'get';
699     }
700
701     // GET forms should not use a CSRF token.
702     if (isset($form['#method']) && $form['#method'] === 'get') {
703       // Merges in a default, this means if you've explicitly set #token to the
704       // the $form_id on a GET form, which we don't recommend, it will work.
705       $form += [
706         '#token' => FALSE,
707       ];
708     }
709
710     // Generate a new #build_id for this form, if none has been set already.
711     // The form_build_id is used as key to cache a particular build of the form.
712     // For multi-step forms, this allows the user to go back to an earlier
713     // build, make changes, and re-submit.
714     // @see self::buildForm()
715     // @see self::rebuildForm()
716     if (!isset($form['#build_id'])) {
717       $form['#build_id'] = 'form-' . Crypt::randomBytesBase64();
718     }
719     $form['form_build_id'] = [
720       '#type' => 'hidden',
721       '#value' => $form['#build_id'],
722       '#id' => $form['#build_id'],
723       '#name' => 'form_build_id',
724       // Form processing and validation requires this value, so ensure the
725       // submitted form value appears literally, regardless of custom #tree
726       // and #parents being set elsewhere.
727       '#parents' => ['form_build_id'],
728       // Prevent user agents from prefilling the build id with earlier values.
729       // When the ajax command "update_build_id" is executed, the user agent
730       // will assume that a user interaction changed the field. Upon a soft
731       // reload of the page, the previous build id will be restored in the
732       // input, causing subsequent ajax callbacks to access the wrong cached
733       // form build. Setting the autocomplete attribute to "off" will tell the
734       // user agent to never reuse the value.
735       // @see https://www.w3.org/TR/2011/WD-html5-20110525/common-input-element-attributes.html#the-autocomplete-attribute
736       '#attributes' => [
737         'autocomplete' => 'off',
738       ],
739     ];
740
741     // Add a token, based on either #token or form_id, to any form displayed to
742     // authenticated users. This ensures that any submitted form was actually
743     // requested previously by the user and protects against cross site request
744     // forgeries.
745     // This does not apply to programmatically submitted forms. Furthermore,
746     // since tokens are session-bound and forms displayed to anonymous users are
747     // very likely cached, we cannot assign a token for them.
748     // During installation, there is no $user yet.
749     // Form constructors may explicitly set #token to FALSE when cross site
750     // request forgery is irrelevant to the form, such as search forms.
751     if ($form_state->isProgrammed() || (isset($form['#token']) && $form['#token'] === FALSE)) {
752       unset($form['#token']);
753     }
754     else {
755       $form['#cache']['contexts'][] = 'user.roles:authenticated';
756       if ($user && $user->isAuthenticated()) {
757         // Generate a public token based on the form id.
758         // Generates a placeholder based on the form ID.
759         $placeholder = 'form_token_placeholder_' . Crypt::hashBase64($form_id);
760         $form['#token'] = $placeholder;
761
762         $form['form_token'] = [
763           '#id' => Html::getUniqueId('edit-' . $form_id . '-form-token'),
764           '#type' => 'token',
765           '#default_value' => $placeholder,
766           // Form processing and validation requires this value, so ensure the
767           // submitted form value appears literally, regardless of custom #tree
768           // and #parents being set elsewhere.
769           '#parents' => ['form_token'],
770           // Instead of setting an actual CSRF token, we've set the placeholder
771           // in form_token's #default_value and #placeholder. These will be
772           // replaced at the very last moment. This ensures forms with a CSRF
773           // token don't have poor cacheability.
774           '#attached' => [
775             'placeholders' => [
776               $placeholder => [
777                 '#lazy_builder' => ['form_builder:renderFormTokenPlaceholder', [$placeholder]]
778               ]
779             ]
780           ],
781           '#cache' => [
782             'max-age' => 0,
783           ],
784         ];
785       }
786     }
787
788     if (isset($form_id)) {
789       $form['form_id'] = [
790         '#type' => 'hidden',
791         '#value' => $form_id,
792         '#id' => Html::getUniqueId("edit-$form_id"),
793         // Form processing and validation requires this value, so ensure the
794         // submitted form value appears literally, regardless of custom #tree
795         // and #parents being set elsewhere.
796         '#parents' => ['form_id'],
797       ];
798     }
799     if (!isset($form['#id'])) {
800       $form['#id'] = Html::getUniqueId($form_id);
801       // Provide a selector usable by JavaScript. As the ID is unique, its not
802       // possible to rely on it in JavaScript.
803       $form['#attributes']['data-drupal-selector'] = Html::getId($form_id);
804     }
805
806     $form += $this->elementInfo->getInfo('form');
807     $form += ['#tree' => FALSE, '#parents' => []];
808     $form['#validate'][] = '::validateForm';
809     $form['#submit'][] = '::submitForm';
810
811     $build_info = $form_state->getBuildInfo();
812     // If no #theme has been set, automatically apply theme suggestions.
813     // The form theme hook itself, which is rendered by form.html.twig,
814     // is in #theme_wrappers. Therefore, the #theme function only has to care
815     // for rendering the inner form elements, not the form itself.
816     if (!isset($form['#theme'])) {
817       $form['#theme'] = [$form_id];
818       if (isset($build_info['base_form_id'])) {
819         $form['#theme'][] = $build_info['base_form_id'];
820       }
821     }
822
823     // Invoke hook_form_alter(), hook_form_BASE_FORM_ID_alter(), and
824     // hook_form_FORM_ID_alter() implementations.
825     $hooks = ['form'];
826     if (isset($build_info['base_form_id'])) {
827       $hooks[] = 'form_' . $build_info['base_form_id'];
828     }
829     $hooks[] = 'form_' . $form_id;
830     $this->moduleHandler->alter($hooks, $form, $form_state, $form_id);
831     $this->themeManager->alter($hooks, $form, $form_state, $form_id);
832   }
833
834   /**
835    * Builds the $form['#action'].
836    *
837    * @return string
838    *   The URL to be used as the $form['#action'].
839    */
840   protected function buildFormAction() {
841     // @todo Use <current> instead of the master request in
842     //   https://www.drupal.org/node/2505339.
843     $request = $this->requestStack->getMasterRequest();
844     $request_uri = $request->getRequestUri();
845
846     // Prevent cross site requests via the Form API by using an absolute URL
847     // when the request uri starts with multiple slashes..
848     if (strpos($request_uri, '//') === 0) {
849       $request_uri = $request->getUri();
850     }
851
852     // @todo Remove this parsing once these are removed from the request in
853     //   https://www.drupal.org/node/2504709.
854     $parsed = UrlHelper::parse($request_uri);
855     unset($parsed['query'][static::AJAX_FORM_REQUEST], $parsed['query'][MainContentViewSubscriber::WRAPPER_FORMAT]);
856     return $parsed['path'] . ($parsed['query'] ? ('?' . UrlHelper::buildQuery($parsed['query'])) : '');
857   }
858
859   /**
860    * {@inheritdoc}
861    */
862   public function setInvalidTokenError(FormStateInterface $form_state) {
863     $this->formValidator->setInvalidTokenError($form_state);
864   }
865
866   /**
867    * {@inheritdoc}
868    */
869   public function validateForm($form_id, &$form, FormStateInterface &$form_state) {
870     $this->formValidator->validateForm($form_id, $form, $form_state);
871   }
872
873   /**
874    * {@inheritdoc}
875    */
876   public function redirectForm(FormStateInterface $form_state) {
877     return $this->formSubmitter->redirectForm($form_state);
878   }
879
880   /**
881    * {@inheritdoc}
882    */
883   public function executeValidateHandlers(&$form, FormStateInterface &$form_state) {
884     $this->formValidator->executeValidateHandlers($form, $form_state);
885   }
886
887   /**
888    * {@inheritdoc}
889    */
890   public function executeSubmitHandlers(&$form, FormStateInterface &$form_state) {
891     $this->formSubmitter->executeSubmitHandlers($form, $form_state);
892   }
893
894   /**
895    * {@inheritdoc}
896    */
897   public function doSubmitForm(&$form, FormStateInterface &$form_state) {
898     throw new \LogicException('Use FormBuilderInterface::processForm() instead.');
899   }
900
901   /**
902    * {@inheritdoc}
903    */
904   public function doBuildForm($form_id, &$element, FormStateInterface &$form_state) {
905     // Initialize as unprocessed.
906     $element['#processed'] = FALSE;
907
908     // Use element defaults.
909     if (isset($element['#type']) && empty($element['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element['#type']))) {
910       // Overlay $info onto $element, retaining preexisting keys in $element.
911       $element += $info;
912       $element['#defaults_loaded'] = TRUE;
913     }
914     // Assign basic defaults common for all form elements.
915     $element += [
916       '#required' => FALSE,
917       '#attributes' => [],
918       '#title_display' => 'before',
919       '#description_display' => 'after',
920       '#errors' => NULL,
921     ];
922
923     // Special handling if we're on the top level form element.
924     if (isset($element['#type']) && $element['#type'] == 'form') {
925       if (!empty($element['#https']) && !UrlHelper::isExternal($element['#action'])) {
926         global $base_root;
927
928         // Not an external URL so ensure that it is secure.
929         $element['#action'] = str_replace('http://', 'https://', $base_root) . $element['#action'];
930       }
931
932       // Store a reference to the complete form in $form_state prior to building
933       // the form. This allows advanced #process and #after_build callbacks to
934       // perform changes elsewhere in the form.
935       $form_state->setCompleteForm($element);
936
937       // Set a flag if we have a correct form submission. This is always TRUE
938       // for programmed forms coming from self::submitForm(), or if the form_id
939       // coming from the POST data is set and matches the current form_id.
940       $input = $form_state->getUserInput();
941       if ($form_state->isProgrammed() || (!empty($input) && (isset($input['form_id']) && ($input['form_id'] == $form_id)))) {
942         $form_state->setProcessInput();
943         if (isset($element['#token'])) {
944           $input = $form_state->getUserInput();
945           if (empty($input['form_token']) || !$this->csrfToken->validate($input['form_token'], $element['#token'])) {
946             // Set an early form error to block certain input processing since
947             // that opens the door for CSRF vulnerabilities.
948             $this->setInvalidTokenError($form_state);
949
950             // This value is checked in self::handleInputElement().
951             $form_state->setInvalidToken(TRUE);
952
953             // Make sure file uploads do not get processed.
954             $this->requestStack->getCurrentRequest()->files = new FileBag();
955           }
956         }
957       }
958       else {
959         $form_state->setProcessInput(FALSE);
960       }
961
962       // All form elements should have an #array_parents property.
963       $element['#array_parents'] = [];
964     }
965
966     if (!isset($element['#id'])) {
967       $unprocessed_id = 'edit-' . implode('-', $element['#parents']);
968       $element['#id'] = Html::getUniqueId($unprocessed_id);
969       // Provide a selector usable by JavaScript. As the ID is unique, its not
970       // possible to rely on it in JavaScript.
971       $element['#attributes']['data-drupal-selector'] = Html::getId($unprocessed_id);
972     }
973     else {
974       // Provide a selector usable by JavaScript. As the ID is unique, its not
975       // possible to rely on it in JavaScript.
976       $element['#attributes']['data-drupal-selector'] = Html::getId($element['#id']);
977     }
978
979     // Add the aria-describedby attribute to associate the form control with its
980     // description.
981     if (!empty($element['#description'])) {
982       $element['#attributes']['aria-describedby'] = $element['#id'] . '--description';
983     }
984     // Handle input elements.
985     if (!empty($element['#input'])) {
986       $this->handleInputElement($form_id, $element, $form_state);
987     }
988     // Allow for elements to expand to multiple elements, e.g., radios,
989     // checkboxes and files.
990     if (isset($element['#process']) && !$element['#processed']) {
991       foreach ($element['#process'] as $callback) {
992         $complete_form = &$form_state->getCompleteForm();
993         $element = call_user_func_array($form_state->prepareCallback($callback), [&$element, &$form_state, &$complete_form]);
994       }
995       $element['#processed'] = TRUE;
996     }
997
998     // We start off assuming all form elements are in the correct order.
999     $element['#sorted'] = TRUE;
1000
1001     // Recurse through all child elements.
1002     $count = 0;
1003     if (isset($element['#access'])) {
1004       $access = $element['#access'];
1005       $inherited_access = NULL;
1006       if (($access instanceof AccessResultInterface && !$access->isAllowed()) || $access === FALSE) {
1007         $inherited_access = $access;
1008       }
1009     }
1010     foreach (Element::children($element) as $key) {
1011       // Prior to checking properties of child elements, their default
1012       // properties need to be loaded.
1013       if (isset($element[$key]['#type']) && empty($element[$key]['#defaults_loaded']) && ($info = $this->elementInfo->getInfo($element[$key]['#type']))) {
1014         $element[$key] += $info;
1015         $element[$key]['#defaults_loaded'] = TRUE;
1016       }
1017
1018       // Don't squash an existing tree value.
1019       if (!isset($element[$key]['#tree'])) {
1020         $element[$key]['#tree'] = $element['#tree'];
1021       }
1022
1023       // Children inherit #access from parent.
1024       if (isset($inherited_access)) {
1025         $element[$key]['#access'] = $inherited_access;
1026       }
1027
1028       // Make child elements inherit their parent's #disabled and #allow_focus
1029       // values unless they specify their own.
1030       foreach (['#disabled', '#allow_focus'] as $property) {
1031         if (isset($element[$property]) && !isset($element[$key][$property])) {
1032           $element[$key][$property] = $element[$property];
1033         }
1034       }
1035
1036       // Don't squash existing parents value.
1037       if (!isset($element[$key]['#parents'])) {
1038         // Check to see if a tree of child elements is present. If so,
1039         // continue down the tree if required.
1040         $element[$key]['#parents'] = $element[$key]['#tree'] && $element['#tree'] ? array_merge($element['#parents'], [$key]) : [$key];
1041       }
1042       // Ensure #array_parents follows the actual form structure.
1043       $array_parents = $element['#array_parents'];
1044       $array_parents[] = $key;
1045       $element[$key]['#array_parents'] = $array_parents;
1046
1047       // Assign a decimal placeholder weight to preserve original array order.
1048       if (!isset($element[$key]['#weight'])) {
1049         $element[$key]['#weight'] = $count / 1000;
1050       }
1051       else {
1052         // If one of the child elements has a weight then we will need to sort
1053         // later.
1054         unset($element['#sorted']);
1055       }
1056       $element[$key] = $this->doBuildForm($form_id, $element[$key], $form_state);
1057       $count++;
1058     }
1059
1060     // The #after_build flag allows any piece of a form to be altered
1061     // after normal input parsing has been completed.
1062     if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
1063       foreach ($element['#after_build'] as $callback) {
1064         $element = call_user_func_array($form_state->prepareCallback($callback), [$element, &$form_state]);
1065       }
1066       $element['#after_build_done'] = TRUE;
1067     }
1068
1069     // If there is a file element, we need to flip a flag so later the
1070     // form encoding can be set.
1071     if (isset($element['#type']) && $element['#type'] == 'file') {
1072       $form_state->setHasFileElement();
1073     }
1074
1075     // Final tasks for the form element after self::doBuildForm() has run for
1076     // all other elements.
1077     if (isset($element['#type']) && $element['#type'] == 'form') {
1078       // If there is a file element, we set the form encoding.
1079       if ($form_state->hasFileElement()) {
1080         $element['#attributes']['enctype'] = 'multipart/form-data';
1081       }
1082
1083       // Allow Ajax submissions to the form action to bypass verification. This
1084       // is especially useful for multipart forms, which cannot be verified via
1085       // a response header.
1086       $element['#attached']['drupalSettings']['ajaxTrustedUrl'][$element['#action']] = TRUE;
1087
1088       // If a form contains a single textfield, and the ENTER key is pressed
1089       // within it, Internet Explorer submits the form with no POST data
1090       // identifying any submit button. Other browsers submit POST data as
1091       // though the user clicked the first button. Therefore, to be as
1092       // consistent as we can be across browsers, if no 'triggering_element' has
1093       // been identified yet, default it to the first button.
1094       $buttons = $form_state->getButtons();
1095       if (!$form_state->isProgrammed() && !$form_state->getTriggeringElement() && !empty($buttons)) {
1096         $form_state->setTriggeringElement($buttons[0]);
1097       }
1098
1099       $triggering_element = $form_state->getTriggeringElement();
1100       // If the triggering element specifies "button-level" validation and
1101       // submit handlers to run instead of the default form-level ones, then add
1102       // those to the form state.
1103       if (isset($triggering_element['#validate'])) {
1104         $form_state->setValidateHandlers($triggering_element['#validate']);
1105       }
1106       if (isset($triggering_element['#submit'])) {
1107         $form_state->setSubmitHandlers($triggering_element['#submit']);
1108       }
1109
1110       // If the triggering element executes submit handlers, then set the form
1111       // state key that's needed for those handlers to run.
1112       if (!empty($triggering_element['#executes_submit_callback'])) {
1113         $form_state->setSubmitted();
1114       }
1115
1116       // Special processing if the triggering element is a button.
1117       if (!empty($triggering_element['#is_button'])) {
1118         // Because there are several ways in which the triggering element could
1119         // have been determined (including from input variables set by
1120         // JavaScript or fallback behavior implemented for IE), and because
1121         // buttons often have their #name property not derived from their
1122         // #parents property, we can't assume that input processing that's
1123         // happened up until here has resulted in
1124         // $form_state->getValue(BUTTON_NAME) being set. But it's common for
1125         // forms to have several buttons named 'op' and switch on
1126         // $form_state->getValue('op') during submit handler execution.
1127         $form_state->setValue($triggering_element['#name'], $triggering_element['#value']);
1128       }
1129     }
1130     return $element;
1131   }
1132
1133   /**
1134    * Helper function to normalize the different callable formats.
1135    *
1136    * @param callable $value_callable
1137    *   The callable to be checked.
1138    *
1139    * @return bool
1140    *   TRUE if the callable is safe even if the CSRF token is invalid, FALSE
1141    *   otherwise.
1142    */
1143   protected function valueCallableIsSafe(callable $value_callable) {
1144     // The same static class method callable may be formatted in two array and
1145     // two string forms:
1146     // ['\Classname', 'methodname']
1147     // ['Classname', 'methodname']
1148     // '\Classname::methodname'
1149     // 'Classname::methodname'
1150     if (is_callable($value_callable, FALSE, $callable_name)) {
1151       // The third parameter of is_callable() is set to a string form, but we
1152       // still have to normalize further by stripping a leading '\'.
1153       return in_array(ltrim($callable_name, '\\'), $this->safeCoreValueCallables);
1154     }
1155     return FALSE;
1156   }
1157
1158   /**
1159    * Adds the #name and #value properties of an input element before rendering.
1160    */
1161   protected function handleInputElement($form_id, &$element, FormStateInterface &$form_state) {
1162     if (!isset($element['#name'])) {
1163       $name = array_shift($element['#parents']);
1164       $element['#name'] = $name;
1165       if ($element['#type'] == 'file') {
1166         // To make it easier to handle files in file.inc, we place all
1167         // file fields in the 'files' array. Also, we do not support
1168         // nested file names.
1169         // @todo Remove this files prefix now?
1170         $element['#name'] = 'files[' . $element['#name'] . ']';
1171       }
1172       elseif (count($element['#parents'])) {
1173         $element['#name'] .= '[' . implode('][', $element['#parents']) . ']';
1174       }
1175       array_unshift($element['#parents'], $name);
1176     }
1177
1178     // Setting #disabled to TRUE results in user input being ignored regardless
1179     // of how the element is themed or whether JavaScript is used to change the
1180     // control's attributes. However, it's good UI to let the user know that
1181     // input is not wanted for the control. HTML supports two attributes for:
1182     // this: http://www.w3.org/TR/html401/interact/forms.html#h-17.12. If a form
1183     // wants to start a control off with one of these attributes for UI
1184     // purposes, only, but still allow input to be processed if it's submitted,
1185     // it can set the desired attribute in #attributes directly rather than
1186     // using #disabled. However, developers should think carefully about the
1187     // accessibility implications of doing so: if the form expects input to be
1188     // enterable under some condition triggered by JavaScript, how would someone
1189     // who has JavaScript disabled trigger that condition? Instead, developers
1190     // should consider whether a multi-step form would be more appropriate
1191     // (#disabled can be changed from step to step). If one still decides to use
1192     // JavaScript to affect when a control is enabled, then it is best for
1193     // accessibility for the control to be enabled in the HTML, and disabled by
1194     // JavaScript on document ready.
1195     if (!empty($element['#disabled'])) {
1196       if (!empty($element['#allow_focus'])) {
1197         $element['#attributes']['readonly'] = 'readonly';
1198       }
1199       else {
1200         $element['#attributes']['disabled'] = 'disabled';
1201       }
1202     }
1203
1204     // With JavaScript or other easy hacking, input can be submitted even for
1205     // elements with #access=FALSE or #disabled=TRUE. For security, these must
1206     // not be processed. Forms that set #disabled=TRUE on an element do not
1207     // expect input for the element, and even forms submitted with
1208     // self::submitForm() must not be able to get around this. Forms that set
1209     // #access=FALSE on an element usually allow access for some users, so forms
1210     // submitted with self::submitForm() may bypass access restriction and be
1211     // treated as high-privilege users instead.
1212     $process_input = empty($element['#disabled']) && (($form_state->isProgrammed() && $form_state->isBypassingProgrammedAccessChecks()) || ($form_state->isProcessingInput() && (!isset($element['#access']) || $element['#access'])));
1213
1214     // Set the element's #value property.
1215     if (!isset($element['#value']) && !array_key_exists('#value', $element)) {
1216       // @todo Once all elements are converted to plugins in
1217       //   https://www.drupal.org/node/2311393, rely on
1218       //   $element['#value_callback'] directly.
1219       $value_callable = !empty($element['#value_callback']) ? $element['#value_callback'] : 'form_type_' . $element['#type'] . '_value';
1220       if (!is_callable($value_callable)) {
1221         $value_callable = '\Drupal\Core\Render\Element\FormElement::valueCallback';
1222       }
1223
1224       if ($process_input) {
1225         // Get the input for the current element. NULL values in the input need
1226         // to be explicitly distinguished from missing input. (see below)
1227         $input_exists = NULL;
1228         $input = NestedArray::getValue($form_state->getUserInput(), $element['#parents'], $input_exists);
1229         // For browser-submitted forms, the submitted values do not contain
1230         // values for certain elements (empty multiple select, unchecked
1231         // checkbox). During initial form processing, we add explicit NULL
1232         // values for such elements in FormState::$input. When rebuilding the
1233         // form, we can distinguish elements having NULL input from elements
1234         // that were not part of the initially submitted form and can therefore
1235         // use default values for the latter, if required. Programmatically
1236         // submitted forms can submit explicit NULL values when calling
1237         // self::submitForm() so we do not modify FormState::$input for them.
1238         if (!$input_exists && !$form_state->isRebuilding() && !$form_state->isProgrammed()) {
1239           // Add the necessary parent keys to FormState::$input and sets the
1240           // element's input value to NULL.
1241           NestedArray::setValue($form_state->getUserInput(), $element['#parents'], NULL);
1242           $input_exists = TRUE;
1243         }
1244         // If we have input for the current element, assign it to the #value
1245         // property, optionally filtered through $value_callback.
1246         if ($input_exists) {
1247           // Skip all value callbacks except safe ones like text if the CSRF
1248           // token was invalid.
1249           if (!$form_state->hasInvalidToken() || $this->valueCallableIsSafe($value_callable)) {
1250             $element['#value'] = call_user_func_array($value_callable, [&$element, $input, &$form_state]);
1251           }
1252           else {
1253             $input = NULL;
1254           }
1255
1256           if (!isset($element['#value']) && isset($input)) {
1257             $element['#value'] = $input;
1258           }
1259         }
1260         // Mark all posted values for validation.
1261         if (isset($element['#value']) || (!empty($element['#required']))) {
1262           $element['#needs_validation'] = TRUE;
1263         }
1264       }
1265       // Load defaults.
1266       if (!isset($element['#value'])) {
1267         // Call #type_value without a second argument to request default_value
1268         // handling.
1269         $element['#value'] = call_user_func_array($value_callable, [&$element, FALSE, &$form_state]);
1270
1271         // Final catch. If we haven't set a value yet, use the explicit default
1272         // value. Avoid image buttons (which come with garbage value), so we
1273         // only get value for the button actually clicked.
1274         if (!isset($element['#value']) && empty($element['#has_garbage_value'])) {
1275           $element['#value'] = isset($element['#default_value']) ? $element['#default_value'] : '';
1276         }
1277       }
1278     }
1279
1280     // Determine which element (if any) triggered the submission of the form and
1281     // keep track of all the clickable buttons in the form for
1282     // \Drupal\Core\Form\FormState::cleanValues(). Enforce the same input
1283     // processing restrictions as above.
1284     if ($process_input) {
1285       // Detect if the element triggered the submission via Ajax.
1286       if ($this->elementTriggeredScriptedSubmission($element, $form_state)) {
1287         $form_state->setTriggeringElement($element);
1288       }
1289
1290       // If the form was submitted by the browser rather than via Ajax, then it
1291       // can only have been triggered by a button, and we need to determine
1292       // which button within the constraints of how browsers provide this
1293       // information.
1294       if (!empty($element['#is_button'])) {
1295         // All buttons in the form need to be tracked for
1296         // \Drupal\Core\Form\FormState::cleanValues() and for the
1297         // self::doBuildForm() code that handles a form submission containing no
1298         // button information in \Drupal::request()->request.
1299         $buttons = $form_state->getButtons();
1300         $buttons[] = $element;
1301         $form_state->setButtons($buttons);
1302         if ($this->buttonWasClicked($element, $form_state)) {
1303           $form_state->setTriggeringElement($element);
1304         }
1305       }
1306     }
1307
1308     // Set the element's value in $form_state->getValues(), but only, if its key
1309     // does not exist yet (a #value_callback may have already populated it).
1310     if (!NestedArray::keyExists($form_state->getValues(), $element['#parents'])) {
1311       $form_state->setValueForElement($element, $element['#value']);
1312     }
1313   }
1314
1315   /**
1316    * Detects if an element triggered the form submission via Ajax.
1317    *
1318    * This detects button or non-button controls that trigger a form submission
1319    * via Ajax or some other scriptable environment. These environments can set
1320    * the special input key '_triggering_element_name' to identify the triggering
1321    * element. If the name alone doesn't identify the element uniquely, the input
1322    * key '_triggering_element_value' may also be set to require a match on
1323    * element value. An example where this is needed is if there are several
1324    * // buttons all named 'op', and only differing in their value.
1325    */
1326   protected function elementTriggeredScriptedSubmission($element, FormStateInterface &$form_state) {
1327     $input = $form_state->getUserInput();
1328     if (!empty($input['_triggering_element_name']) && $element['#name'] == $input['_triggering_element_name']) {
1329       if (empty($input['_triggering_element_value']) || $input['_triggering_element_value'] == $element['#value']) {
1330         return TRUE;
1331       }
1332     }
1333     return FALSE;
1334   }
1335
1336   /**
1337    * Determines if a given button triggered the form submission.
1338    *
1339    * This detects button controls that trigger a form submission by being
1340    * clicked and having the click processed by the browser rather than being
1341    * captured by JavaScript. Essentially, it detects if the button's name and
1342    * value are part of the POST data, but with extra code to deal with the
1343    * convoluted way in which browsers submit data for image button clicks.
1344    *
1345    * This does not detect button clicks processed by Ajax (that is done in
1346    * self::elementTriggeredScriptedSubmission()) and it does not detect form
1347    * submissions from Internet Explorer in response to an ENTER key pressed in a
1348    * textfield (self::doBuildForm() has extra code for that).
1349    *
1350    * Because this function contains only part of the logic needed to determine
1351    * $form_state->getTriggeringElement(), it should not be called from anywhere
1352    * other than within the Form API. Form validation and submit handlers needing
1353    * to know which button was clicked should get that information from
1354    * $form_state->getTriggeringElement().
1355    */
1356   protected function buttonWasClicked($element, FormStateInterface &$form_state) {
1357     // First detect normal 'vanilla' button clicks. Traditionally, all standard
1358     // buttons on a form share the same name (usually 'op'), and the specific
1359     // return value is used to determine which was clicked. This ONLY works as
1360     // long as $form['#name'] puts the value at the top level of the tree of
1361     // \Drupal::request()->request data.
1362     $input = $form_state->getUserInput();
1363     // The input value attribute is treated as CDATA by browsers. This means
1364     // that they replace character entities with characters. Therefore, we need
1365     // to decode the value in $element['#value']. For more details see
1366     // http://www.w3.org/TR/html401/types.html#type-cdata.
1367     if (isset($input[$element['#name']]) && $input[$element['#name']] == Html::decodeEntities($element['#value'])) {
1368       return TRUE;
1369     }
1370     // When image buttons are clicked, browsers do NOT pass the form element
1371     // value in \Drupal::request()->Request. Instead they pass an integer
1372     // representing the coordinates of the click on the button image. This means
1373     // that image buttons MUST have unique $form['#name'] values, but the
1374     // details of their \Drupal::request()->request data should be ignored.
1375     elseif (!empty($element['#has_garbage_value']) && isset($element['#value']) && $element['#value'] !== '') {
1376       return TRUE;
1377     }
1378     return FALSE;
1379   }
1380
1381   /**
1382    * Wraps file_upload_max_size().
1383    *
1384    * @return string
1385    *   A translated string representation of the size of the file size limit
1386    *   based on the PHP upload_max_filesize and post_max_size.
1387    */
1388   protected function getFileUploadMaxSize() {
1389     return file_upload_max_size();
1390   }
1391
1392   /**
1393    * Gets the current active user.
1394    *
1395    * @return \Drupal\Core\Session\AccountInterface
1396    */
1397   protected function currentUser() {
1398     if (!$this->currentUser && \Drupal::hasService('current_user')) {
1399       $this->currentUser = \Drupal::currentUser();
1400     }
1401     return $this->currentUser;
1402   }
1403
1404 }