‪TYPO3CMS  9.5
FormRuntime.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It originated from the Neos.Form package (www.neos.io)
9  *
10  * It is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU General Public License, either version 2
12  * of the License, or any later version.
13  *
14  * For the full copyright and license information, please read the
15  * LICENSE.txt file that was distributed with this source code.
16  *
17  * The TYPO3 project - inspiring people to share!
18  */
19 
20 use Psr\Http\Message\ServerRequestInterface;
52 use ‪TYPO3\CMS\Form\Exception as FormException;
57 
96 class ‪FormRuntime implements ‪RootRenderableInterface, \ArrayAccess
97 {
98  const ‪HONEYPOT_NAME_SESSION_IDENTIFIER = 'tx_form_honeypot_name_';
99 
103  protected ‪$objectManager;
104 
108  protected ‪$formDefinition;
109 
113  protected ‪$request;
114 
118  protected ‪$response;
119 
123  protected ‪$formState;
124 
131  protected ‪$formSession;
132 
143  protected ‪$currentPage;
144 
151  protected ‪$lastDisplayedPage;
152 
156  protected ‪$hashService;
157 
163  protected ‪$currentSiteLanguage = null;
164 
170  protected ‪$currentFinisher = null;
171 
175  protected ‪$configurationManager;
176 
181  public function ‪injectHashService(\‪TYPO3\CMS\‪Extbase\Security\Cryptography\HashService ‪$hashService)
182  {
183  $this->hashService = ‪$hashService;
184  }
185 
190  public function ‪injectObjectManager(\‪TYPO3\CMS\‪Extbase\Object\ObjectManagerInterface ‪$objectManager)
191  {
192  $this->objectManager = ‪$objectManager;
193  }
194 
198  public function ‪injectConfigurationManager(ConfigurationManagerInterface ‪$configurationManager)
199  {
200  $this->configurationManager = ‪$configurationManager;
201  }
202 
208  public function ‪__construct(FormDefinition ‪$formDefinition, Request ‪$request, Response ‪$response)
209  {
210  $this->formDefinition = ‪$formDefinition;
211  $arguments = ‪$request->‪getArguments();
212  $this->request = clone ‪$request;
213  $formIdentifier = $this->formDefinition->getIdentifier();
214  if (isset($arguments[$formIdentifier])) {
215  $this->request->‪setArguments($arguments[$formIdentifier]);
216  }
217 
218  $this->response = ‪$response;
219  }
220 
224  public function ‪initializeObject()
225  {
230  $this->‪processVariants();
233 
234  // Only validate and set form values within the form state
235  // if the current request is not the very first request
236  // and the current request can be processed (POST request and uncached).
237  if (!$this->‪isFirstRequest() && $this->‪canProcessFormSubmission()) {
239  }
240 
241  $this->‪renderHoneypot();
242  }
243 
247  protected function ‪initializeFormSessionFromRequest(): void
248  {
249  // Initialize the form session only if the current request can be processed
250  // (POST request and uncached) to ensure unique sessions for each form submitter.
252  return;
253  }
254 
255  $sessionIdentifierFromRequest = $this->request->getInternalArgument('__session');
256  $this->formSession = GeneralUtility::makeInstance(FormSession::class, $sessionIdentifierFromRequest);
257  }
258 
263  protected function ‪initializeFormStateFromRequest()
264  {
265  // Only try to reconstitute the form state if the current request
266  // is not the very first request and if the current request can
267  // be processed (POST request and uncached).
268  $serializedFormStateWithHmac = $this->request->getInternalArgument('__state');
269  if ($serializedFormStateWithHmac === null || !$this->‪canProcessFormSubmission()) {
270  $this->formState = GeneralUtility::makeInstance(FormState::class);
271  } else {
272  try {
273  $serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac);
274  } catch (InvalidHashException | InvalidArgumentForHashGenerationException $e) {
275  throw new BadRequestException('The HMAC of the form state could not be validated.', 1581862823);
276  }
277  $this->formState = unserialize(base64_decode($serializedFormState));
278  }
279  }
280 
281  protected function ‪triggerAfterFormStateInitialized(): void
282  {
283  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterFormStateInitialized'] ?? [] as $className) {
284  $hookObj = GeneralUtility::makeInstance($className);
285  if ($hookObj instanceof ‪AfterFormStateInitializedInterface) {
286  $hookObj->afterFormStateInitialized($this);
287  }
288  }
289  }
290 
294  protected function ‪initializeCurrentPageFromRequest()
295  {
296  // If there was no previous form submissions or if the current request
297  // can't be processed (no POST request and/or cached) then display the first
298  // form step
299  if (!$this->formState->isFormSubmitted() || !$this->canProcessFormSubmission()) {
300  $this->currentPage = $this->formDefinition->getPageByIndex(0);
301  $renderingOptions = $this->currentPage->getRenderingOptions();
302 
303  if (!$this->currentPage->isEnabled()) {
304  throw new FormException('Disabling the first page is not allowed', 1527186844);
305  }
306 
307  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterInitializeCurrentPage'] ?? [] as $className) {
308  $hookObj = GeneralUtility::makeInstance($className);
309  if (method_exists($hookObj, 'afterInitializeCurrentPage')) {
310  $this->currentPage = $hookObj->afterInitializeCurrentPage(
311  $this,
312  $this->currentPage,
313  null,
314  $this->request->getArguments()
315  );
316  }
317  }
318  return;
319  }
320 
321  $this->lastDisplayedPage = $this->formDefinition->getPageByIndex($this->formState->getLastDisplayedPageIndex());
322  $currentPageIndex = (int)$this->request->getInternalArgument('__currentPage');
323 
324  if ($this->‪userWentBackToPreviousStep()) {
325  if ($currentPageIndex < $this->lastDisplayedPage->getIndex()) {
326  $currentPageIndex = $this->lastDisplayedPage->getIndex();
327  }
328  } else {
329  if ($currentPageIndex > $this->lastDisplayedPage->getIndex() + 1) {
330  $currentPageIndex = $this->lastDisplayedPage->getIndex() + 1;
331  }
332  }
333 
334  if ($currentPageIndex >= count($this->formDefinition->getPages())) {
335  // Last Page
336  $this->currentPage = null;
337  } else {
338  $this->currentPage = $this->formDefinition->getPageByIndex($currentPageIndex);
339  $renderingOptions = $this->currentPage->getRenderingOptions();
340 
341  if (!$this->currentPage->isEnabled()) {
342  if ($currentPageIndex === 0) {
343  throw new FormException('Disabling the first page is not allowed', 1527186845);
344  }
345 
346  if ($this->‪userWentBackToPreviousStep()) {
347  $this->currentPage = $this->‪getPreviousEnabledPage();
348  } else {
349  $this->currentPage = $this->‪getNextEnabledPage();
350  }
351  }
352  }
353 
354  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterInitializeCurrentPage'] ?? [] as $className) {
355  $hookObj = GeneralUtility::makeInstance($className);
356  if (method_exists($hookObj, 'afterInitializeCurrentPage')) {
357  $this->currentPage = $hookObj->afterInitializeCurrentPage(
358  $this,
359  $this->currentPage,
360  $this->lastDisplayedPage,
361  $this->request->getArguments()
362  );
363  }
364  }
365  }
366 
370  protected function ‪initializeHoneypotFromRequest()
371  {
372  $renderingOptions = $this->formDefinition->getRenderingOptions();
373  if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') {
374  return;
375  }
376 
377  ‪ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']);
378 
379  if (!$this->‪isFirstRequest()) {
380  $elementsCount = count($this->lastDisplayedPage->getElements());
381  if ($elementsCount === 0) {
382  return;
383  }
384 
385  $honeypotNameFromSession = $this->‪getHoneypotNameFromSession($this->lastDisplayedPage);
386  if ($honeypotNameFromSession) {
387  $honeypotElement = $this->lastDisplayedPage->createElement($honeypotNameFromSession, $renderingOptions['honeypot']['formElementToUse']);
388  ‪$validator = $this->objectManager->get(EmptyValidator::class);
389  $honeypotElement->addValidator(‪$validator);
390  }
391  }
392  }
393 
397  protected function ‪renderHoneypot()
398  {
399  $renderingOptions = $this->formDefinition->getRenderingOptions();
400  if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') {
401  return;
402  }
403 
404  ‪ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']);
405 
406  if (!$this->‪isAfterLastPage()) {
407  $elementsCount = count($this->currentPage->getElements());
408  if ($elementsCount === 0) {
409  return;
410  }
411 
412  if (!$this->‪isFirstRequest()) {
413  $honeypotNameFromSession = $this->‪getHoneypotNameFromSession($this->lastDisplayedPage);
414  if ($honeypotNameFromSession) {
415  $honeypotElement = $this->formDefinition->getElementByIdentifier($honeypotNameFromSession);
416  if ($honeypotElement instanceof FormElementInterface) {
417  $this->lastDisplayedPage->removeElement($honeypotElement);
418  }
419  }
420  }
421 
422  $elementsCount = count($this->currentPage->getElements());
423  $randomElementNumber = mt_rand(0, $elementsCount - 1);
424  $honeypotName = substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, mt_rand(5, 26));
425 
426  $referenceElement = $this->currentPage->getElements()[$randomElementNumber];
427  $honeypotElement = $this->currentPage->createElement($honeypotName, $renderingOptions['honeypot']['formElementToUse']);
428  ‪$validator = $this->objectManager->get(EmptyValidator::class);
429 
430  $honeypotElement->addValidator(‪$validator);
431  if (mt_rand(0, 1) === 1) {
432  $this->currentPage->moveElementAfter($honeypotElement, $referenceElement);
433  } else {
434  $this->currentPage->moveElementBefore($honeypotElement, $referenceElement);
435  }
436  $this->‪setHoneypotNameInSession($this->currentPage, $honeypotName);
437  }
438  }
439 
444  protected function ‪getHoneypotNameFromSession(Page $page)
445  {
446  if ($this->‪isFrontendUserAuthenticated()) {
447  $honeypotNameFromSession = $this->‪getFrontendUser()->‪getKey(
448  'user',
449  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier()
450  );
451  } else {
452  $honeypotNameFromSession = $this->‪getFrontendUser()->‪getKey(
453  'ses',
454  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier()
455  );
456  }
457  return $honeypotNameFromSession;
458  }
459 
464  protected function ‪setHoneypotNameInSession(Page $page, string $honeypotName)
465  {
466  if ($this->‪isFrontendUserAuthenticated()) {
467  $this->‪getFrontendUser()->‪setKey(
468  'user',
469  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier(),
470  $honeypotName
471  );
472  } else {
473  $this->‪getFrontendUser()->‪setKey(
474  'ses',
475  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier(),
476  $honeypotName
477  );
478  }
479  }
480 
486  protected function ‪isFrontendUserAuthenticated(): bool
487  {
488  return (bool)GeneralUtility::makeInstance(Context::class)
489  ->getPropertyFromAspect('frontend.user', 'isLoggedIn', false);
490  }
491 
494  protected function ‪processVariants()
495  {
496  $conditionResolver = $this->‪getConditionResolver();
497 
498  $renderables = array_merge([$this->formDefinition], $this->formDefinition->getRenderablesRecursively());
499  foreach ($renderables as $renderable) {
500  if ($renderable instanceof VariableRenderableInterface) {
501  $variants = $renderable->getVariants();
502  foreach ($variants as $variant) {
503  if ($variant->conditionMatches($conditionResolver)) {
504  $variant->apply();
505  }
506  }
507  }
508  }
509  }
510 
516  protected function ‪isAfterLastPage(): bool
517  {
518  return $this->currentPage === null;
519  }
520 
526  protected function ‪isFirstRequest(): bool
527  {
528  return $this->lastDisplayedPage === null;
529  }
530 
534  protected function ‪isPostRequest(): bool
535  {
536  return $this->‪getRequest()->‪getMethod() === 'POST';
537  }
538 
547  protected function ‪isRenderedCached(): bool
548  {
549  $contentObject = $this->configurationManager->getContentObject();
550  return $contentObject === null
551  ? true
552  // @todo this does not work when rendering a cached `FLUIDTEMPLATE` (not nested in `COA_INT`)
553  : $contentObject->getUserObjectType() === ‪ContentObjectRenderer::OBJECTTYPE_USER;
554  }
555 
559  protected function ‪processSubmittedFormValues()
560  {
561  $result = $this->‪mapAndValidatePage($this->lastDisplayedPage);
562  if ($result->hasErrors() && !$this->userWentBackToPreviousStep()) {
563  $this->currentPage = ‪$this->lastDisplayedPage;
564  $this->request->setOriginalRequestMappingResults($result);
565  }
566  }
567 
573  protected function ‪userWentBackToPreviousStep(): bool
574  {
575  return !$this->‪isAfterLastPage() && !$this->‪isFirstRequest() && $this->currentPage->getIndex() < $this->lastDisplayedPage->getIndex();
576  }
577 
583  protected function ‪mapAndValidatePage(Page $page): Result
584  {
585  $result = $this->objectManager->get(Result::class);
586  $requestArguments = $this->request->getArguments();
587 
588  $propertyPathsForWhichPropertyMappingShouldHappen = [];
589  $registerPropertyPaths = function ($propertyPath) use (&$propertyPathsForWhichPropertyMappingShouldHappen) {
590  $propertyPathParts = explode('.', $propertyPath);
591  $accumulatedPropertyPathParts = [];
592  foreach ($propertyPathParts as $propertyPathPart) {
593  $accumulatedPropertyPathParts[] = $propertyPathPart;
594  $temporaryPropertyPath = implode('.', $accumulatedPropertyPathParts);
595  $propertyPathsForWhichPropertyMappingShouldHappen[$temporaryPropertyPath] = $temporaryPropertyPath;
596  }
597  };
598 
599  $value = null;
600 
601  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterSubmit'] ?? [] as $className) {
602  $hookObj = GeneralUtility::makeInstance($className);
603  if (method_exists($hookObj, 'afterSubmit')) {
604  $value = $hookObj->afterSubmit(
605  $this,
606  $page,
607  $value,
608  $requestArguments
609  );
610  }
611  }
612 
613  foreach ($page->getElementsRecursively() as $element) {
614  if (!$element->isEnabled()) {
615  continue;
616  }
617 
618  try {
619  $value = ‪ArrayUtility::getValueByPath($requestArguments, $element->getIdentifier(), '.');
620  } catch (MissingArrayPathException $exception) {
621  $value = null;
622  }
623 
624  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterSubmit'] ?? [] as $className) {
625  $hookObj = GeneralUtility::makeInstance($className);
626  if (method_exists($hookObj, 'afterSubmit')) {
627  $value = $hookObj->afterSubmit(
628  $this,
629  $element,
630  $value,
631  $requestArguments
632  );
633  }
634  }
635 
636  $this->formState->setFormValue($element->getIdentifier(), $value);
637  $registerPropertyPaths($element->getIdentifier());
638  }
639 
640  // The more parts the path has, the more early it is processed
641  usort($propertyPathsForWhichPropertyMappingShouldHappen, function ($a, $b) {
642  return substr_count($b, '.') - substr_count($a, '.');
643  });
644 
645  $processingRules = $this->formDefinition->getProcessingRules();
646 
647  foreach ($propertyPathsForWhichPropertyMappingShouldHappen as $propertyPath) {
648  if (isset($processingRules[$propertyPath])) {
649  $processingRule = $processingRules[$propertyPath];
650  $value = $this->formState->getFormValue($propertyPath);
651  try {
652  $value = $processingRule->process($value);
653  } catch (‪PropertyException $exception) {
654  throw new PropertyMappingException(
655  'Failed to process FormValue at "' . $propertyPath . '" from "' . gettype($value) . '" to "' . $processingRule->getDataType() . '"',
656  1480024933,
657  $exception
658  );
659  }
660  $result->forProperty($this->‪getIdentifier() . '.' . $propertyPath)->merge($processingRule->getProcessingMessages());
661  $this->formState->setFormValue($propertyPath, $value);
662  }
663  }
664 
665  return $result;
666  }
667 
676  public function ‪overrideCurrentPage(int $pageIndex)
677  {
678  $this->currentPage = $this->formDefinition->getPageByIndex($pageIndex);
679  }
680 
687  public function ‪render()
688  {
689  if ($this->‪isAfterLastPage()) {
690  return $this->‪invokeFinishers();
691  }
692  $this->‪processVariants();
693 
694  $this->formState->setLastDisplayedPageIndex($this->currentPage->getIndex());
695 
696  if ($this->formDefinition->getRendererClassName() === '') {
697  throw new RenderingException(sprintf('The form definition "%s" does not have a rendererClassName set.', $this->formDefinition->getIdentifier()), 1326095912);
698  }
699  $rendererClassName = $this->formDefinition->getRendererClassName();
700  $renderer = $this->objectManager->get($rendererClassName);
701  if (!($renderer instanceof RendererInterface)) {
702  throw new RenderingException(sprintf('The renderer "%s" des not implement RendererInterface', $rendererClassName), 1326096024);
703  }
704 
705  $controllerContext = $this->‪getControllerContext();
706 
707  $renderer->setControllerContext($controllerContext);
708  $renderer->setFormRuntime($this);
709  return $renderer->render();
710  }
711 
717  protected function ‪invokeFinishers(): string
718  {
719  $finisherContext = $this->objectManager->get(
720  FinisherContext::class,
721  $this,
722  $this->‪getControllerContext()
723  );
724 
725  ‪$output = '';
726  $originalContent = $this->response->getContent();
727  $this->response->setContent(null);
728  foreach ($this->formDefinition->getFinishers() as $finisher) {
729  $this->currentFinisher = $finisher;
730  $this->‪processVariants();
731 
732  $finisherOutput = $finisher->execute($finisherContext);
733  if (is_string($finisherOutput) && !empty($finisherOutput)) {
734  ‪$output .= $finisherOutput;
735  } else {
736  ‪$output .= $this->response->getContent();
737  $this->response->setContent(null);
738  }
739 
740  if ($finisherContext->isCancelled()) {
741  break;
742  }
743  }
744  $this->response->setContent($originalContent);
745 
746  return ‪$output;
747  }
748 
752  public function ‪getIdentifier(): string
753  {
754  return $this->formDefinition->getIdentifier();
755  }
756 
765  public function ‪getRequest(): ‪Request
766  {
767  return ‪$this->request;
768  }
769 
778  public function ‪getResponse(): ‪Response
779  {
781  }
782 
792  public function ‪canProcessFormSubmission(): bool
793  {
794  return $this->‪isPostRequest() && !$this->‪isRenderedCached();
795  }
796 
801  public function ‪getFormSession(): ?FormSession
802  {
803  return ‪$this->formSession;
804  }
805 
811  public function ‪getCurrentPage(): ?Page
812  {
813  return ‪$this->currentPage;
814  }
815 
821  public function ‪getPreviousPage(): ?Page
822  {
823  $previousPageIndex = $this->currentPage->getIndex() - 1;
824  if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) {
825  return $this->formDefinition->getPageByIndex($previousPageIndex);
826  }
827  return null;
828  }
829 
835  public function ‪getNextPage(): ?Page
836  {
837  $nextPageIndex = $this->currentPage->getIndex() + 1;
838  if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) {
839  return $this->formDefinition->getPageByIndex($nextPageIndex);
840  }
841  return null;
842  }
843 
850  public function ‪getPreviousEnabledPage(): ?Page
851  {
852  $previousPage = null;
853  $previousPageIndex = $this->currentPage->getIndex() - 1;
854  while ($previousPageIndex >= 0) {
855  if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) {
856  $previousPage = $this->formDefinition->getPageByIndex($previousPageIndex);
857 
858  if ($previousPage->isEnabled()) {
859  break;
860  }
861 
862  $previousPage = null;
863  $previousPageIndex--;
864  } else {
865  $previousPage = null;
866  break;
867  }
868  }
869 
870  return $previousPage;
871  }
872 
879  public function ‪getNextEnabledPage(): ?Page
880  {
881  $nextPage = null;
882  $pageCount = count($this->formDefinition->getPages());
883  $nextPageIndex = $this->currentPage->getIndex() + 1;
884 
885  while ($nextPageIndex < $pageCount) {
886  if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) {
887  $nextPage = $this->formDefinition->getPageByIndex($nextPageIndex);
888  $renderingOptions = $nextPage->getRenderingOptions();
889  if (
890  !isset($renderingOptions['enabled'])
891  || (bool)$renderingOptions['enabled']
892  ) {
893  break;
894  }
895  $nextPage = null;
896  $nextPageIndex++;
897  } else {
898  $nextPage = null;
899  break;
900  }
901  }
902 
903  return $nextPage;
904  }
905 
909  protected function ‪getControllerContext(): ControllerContext
910  {
911  $uriBuilder = $this->objectManager->get(UriBuilder::class);
912  $uriBuilder->setRequest($this->request);
913  $controllerContext = $this->objectManager->get(ControllerContext::class);
914  $controllerContext->setRequest($this->request);
915  $controllerContext->setResponse($this->response);
916  $controllerContext->setArguments($this->objectManager->get(Arguments::class, []));
917  $controllerContext->setUriBuilder($uriBuilder);
918  return $controllerContext;
919  }
920 
928  public function ‪getType(): string
929  {
930  return $this->formDefinition->getType();
931  }
932 
938  public function ‪offsetExists($identifier)
939  {
940  if ($this->‪getElementValue($identifier) !== null) {
941  return true;
942  }
943 
944  if (is_callable([$this, 'get' . ucfirst($identifier)])) {
945  return true;
946  }
947  if (is_callable([$this, 'has' . ucfirst($identifier)])) {
948  return true;
949  }
950  if (is_callable([$this, 'is' . ucfirst($identifier)])) {
951  return true;
952  }
953  if (property_exists($this, $identifier)) {
954  $propertyReflection = new \ReflectionProperty($this, $identifier);
955  return $propertyReflection->isPublic();
956  }
957 
958  return false;
959  }
960 
966  public function ‪offsetGet($identifier)
967  {
968  if ($this->‪getElementValue($identifier) !== null) {
969  return $this->‪getElementValue($identifier);
970  }
971  $getterMethodName = 'get' . ucfirst($identifier);
972  if (is_callable([$this, $getterMethodName])) {
973  return $this->{$getterMethodName}();
974  }
975  return null;
976  }
977 
983  public function ‪offsetSet($identifier, $value)
984  {
985  $this->formState->setFormValue($identifier, $value);
986  }
987 
992  public function ‪offsetUnset($identifier)
993  {
994  $this->formState->setFormValue($identifier, null);
995  }
996 
1003  public function ‪getElementValue(string $identifier)
1004  {
1005  $formValue = $this->formState->getFormValue($identifier);
1006  if ($formValue !== null) {
1007  return $formValue;
1008  }
1009  return $this->formDefinition->getElementDefaultValueByIdentifier($identifier);
1010  }
1011 
1015  public function ‪getPages(): array
1016  {
1017  return $this->formDefinition->getPages();
1018  }
1019 
1024  public function ‪getFormState(): ?FormState
1025  {
1026  return ‪$this->formState;
1027  }
1028 
1034  public function ‪getRenderingOptions(): array
1035  {
1036  return $this->formDefinition->getRenderingOptions();
1037  }
1038 
1045  public function ‪getRendererClassName(): string
1046  {
1047  return $this->formDefinition->getRendererClassName();
1048  }
1049 
1055  public function ‪getLabel(): string
1056  {
1057  return $this->formDefinition->getLabel();
1058  }
1059 
1065  public function ‪getTemplateName(): string
1066  {
1067  return $this->formDefinition->getTemplateName();
1068  }
1069 
1075  public function ‪getFormDefinition(): FormDefinition
1076  {
1077  return ‪$this->formDefinition;
1078  }
1079 
1085  public function ‪getCurrentSiteLanguage(): ?SiteLanguage
1086  {
1088  }
1089 
1099  {
1100  $this->currentSiteLanguage = ‪$currentSiteLanguage;
1101  }
1102 
1107  protected function ‪initializeCurrentSiteLanguage(): void
1108  {
1109  if (
1110  ‪$GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
1111  && ‪$GLOBALS['TYPO3_REQUEST']->getAttribute('language') instanceof SiteLanguage
1112  ) {
1113  $this->currentSiteLanguage = ‪$GLOBALS['TYPO3_REQUEST']->getAttribute('language');
1114  } else {
1115  $pageId = 0;
1116  $languageId = (int)GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id', 0);
1117 
1118  if (TYPO3_MODE === 'FE') {
1119  $pageId = $this->‪getTypoScriptFrontendController()->id;
1120  }
1121 
1122  $fakeSiteConfiguration = [
1123  'languages' => [
1124  [
1125  'languageId' => $languageId,
1126  'title' => 'Dummy',
1127  'navigationTitle' => '',
1128  'typo3Language' => '',
1129  'flag' => '',
1130  'locale' => '',
1131  'iso-639-1' => '',
1132  'hreflang' => '',
1133  'direction' => '',
1134  ],
1135  ],
1136  ];
1137 
1138  $this->currentSiteLanguage = GeneralUtility::makeInstance(Site::class, 'form-dummy', $pageId, $fakeSiteConfiguration)
1139  ->getLanguageById($languageId);
1140  }
1141  }
1142 
1148  public function ‪getCurrentFinisher(): ?FinisherInterface
1149  {
1151  }
1152 
1156  protected function ‪getConditionResolver(): Resolver
1157  {
1158  $formValues = array_replace_recursive(
1159  $this->‪getFormState()->getFormValues(),
1160  $this->‪getRequest()->getArguments()
1161  );
1162  $page = $this->‪getCurrentPage() ?? $this->‪getFormDefinition()->‪getPageByIndex(0);
1163 
1164  $finisherIdentifier = '';
1165  if ($this->‪getCurrentFinisher() !== null) {
1166  if (method_exists($this->‪getCurrentFinisher(), 'getFinisherIdentifier')) {
1167  $finisherIdentifier = $this->‪getCurrentFinisher()->getFinisherIdentifier();
1168  } else {
1169  $finisherIdentifier = (new \ReflectionClass($this->‪getCurrentFinisher()))->getShortName();
1170  $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier);
1171  }
1172  }
1173 
1174  return GeneralUtility::makeInstance(
1175  Resolver::class,
1176  'form',
1177  [
1178  // some shortcuts
1179  'formRuntime' => $this,
1180  'formValues' => $formValues,
1181  'stepIdentifier' => $page->getIdentifier(),
1182  'stepType' => $page->getType(),
1183  'finisherIdentifier' => $finisherIdentifier,
1184  ],
1185  ‪$GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(ServerRequest::class)
1186  );
1187  }
1193  {
1194  return $this->‪getTypoScriptFrontendController()->fe_user;
1195  }
1196 
1201  {
1202  return ‪$GLOBALS['TSFE'];
1203  }
1204 }
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isAfterLastPage
‪bool isAfterLastPage()
Definition: FormRuntime.php:504
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPreviousPage
‪Page null getPreviousPage()
Definition: FormRuntime.php:809
‪TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection\getElementsRecursively
‪FormElementInterface[] getElementsRecursively()
Definition: AbstractSection.php:74
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formState
‪TYPO3 CMS Form Domain Runtime FormState $formState
Definition: FormRuntime.php:118
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime
Definition: FormRuntime.php:97
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\overrideCurrentPage
‪overrideCurrentPage(int $pageIndex)
Definition: FormRuntime.php:664
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\HONEYPOT_NAME_SESSION_IDENTIFIER
‪const HONEYPOT_NAME_SESSION_IDENTIFIER
Definition: FormRuntime.php:98
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER
‪const OBJECTTYPE_USER
Definition: ContentObjectRenderer.php:438
‪TYPO3\CMS\Form\Mvc\Validation\EmptyValidator
Definition: EmptyValidator.php:26
‪TYPO3\CMS\Extbase\Property\Exception
Definition: DuplicateObjectException.php:2
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$request
‪TYPO3 CMS Extbase Mvc Web Request $request
Definition: FormRuntime.php:110
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRenderingOptions
‪array getRenderingOptions()
Definition: FormRuntime.php:1022
‪TYPO3\CMS\Form\Domain\Finishers\FinisherInterface
Definition: FinisherInterface.php:27
‪TYPO3\CMS\Extbase\Annotation
Definition: IgnoreValidation.php:4
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isFirstRequest
‪bool isFirstRequest()
Definition: FormRuntime.php:514
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectHashService
‪injectHashService(\TYPO3\CMS\Extbase\Security\Cryptography\HashService $hashService)
Definition: FormRuntime.php:169
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isPostRequest
‪bool isPostRequest()
Definition: FormRuntime.php:522
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFrontendUser
‪FrontendUserAuthentication getFrontendUser()
Definition: FormRuntime.php:1180
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getHoneypotNameFromSession
‪string null getHoneypotNameFromSession(Page $page)
Definition: FormRuntime.php:432
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$lastDisplayedPage
‪TYPO3 CMS Form Domain Model FormElements Page $lastDisplayedPage
Definition: FormRuntime.php:143
‪TYPO3\CMS\Form\Domain\Runtime\Exception\PropertyMappingException
Definition: PropertyMappingException.php:26
‪TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
Definition: UriBuilder.php:29
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeFormSessionFromRequest
‪initializeFormSessionFromRequest()
Definition: FormRuntime.php:235
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getControllerContext
‪ControllerContext getControllerContext()
Definition: FormRuntime.php:897
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:26
‪TYPO3
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentSiteLanguage
‪SiteLanguage getCurrentSiteLanguage()
Definition: FormRuntime.php:1073
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isFrontendUserAuthenticated
‪bool isFrontendUserAuthenticated()
Definition: FormRuntime.php:474
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getTypoScriptFrontendController
‪TypoScriptFrontendController getTypoScriptFrontendController()
Definition: FormRuntime.php:1188
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formSession
‪FormSession null $formSession
Definition: FormRuntime.php:125
‪TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
Definition: ControllerContext.php:21
‪TYPO3\CMS\Form\Domain\Renderer\RendererInterface
Definition: RendererInterface.php:31
‪TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext\setRequest
‪setRequest(\TYPO3\CMS\Extbase\Mvc\Request $request)
Definition: ControllerContext.php:71
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeHoneypotFromRequest
‪initializeHoneypotFromRequest()
Definition: FormRuntime.php:358
‪TYPO3\CMS\Form\Domain\Runtime\FormState
Definition: FormState.php:32
‪TYPO3\CMS\Extbase\Mvc\Controller\Arguments
Definition: Arguments.php:22
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\canProcessFormSubmission
‪bool canProcessFormSubmission()
Definition: FormRuntime.php:780
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getNextEnabledPage
‪Page null getNextEnabledPage()
Definition: FormRuntime.php:867
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:22
‪TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
Definition: InvalidArgumentForHashGenerationException.php:21
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPages
‪array< Page > getPages()
Definition: FormRuntime.php:1003
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\invokeFinishers
‪string invokeFinishers()
Definition: FormRuntime.php:705
‪TYPO3\CMS\Core\Error\Http\BadRequestException
Definition: BadRequestException.php:21
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetSet
‪offsetSet($identifier, $value)
Definition: FormRuntime.php:971
‪TYPO3\CMS\Extbase\Mvc\Web\Request\getMethod
‪string getMethod()
Definition: Request.php:101
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getNextPage
‪Page null getNextPage()
Definition: FormRuntime.php:823
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRendererClassName
‪string getRendererClassName()
Definition: FormRuntime.php:1033
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getConditionResolver
‪Resolver getConditionResolver()
Definition: FormRuntime.php:1144
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\Lifecycle\AfterFormStateInitializedInterface
Definition: AfterFormStateInitializedInterface.php:27
‪TYPO3\CMS\Extbase\Error\Result
Definition: Result.php:20
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\processSubmittedFormValues
‪processSubmittedFormValues()
Definition: FormRuntime.php:547
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getLabel
‪string getLabel()
Definition: FormRuntime.php:1043
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getType
‪string getType()
Definition: FormRuntime.php:916
‪TYPO3\CMS\Form\Domain\Model\FormElements\Page
Definition: Page.php:40
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeFormStateFromRequest
‪initializeFormStateFromRequest()
Definition: FormRuntime.php:251
‪TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable\getIndex
‪int getIndex()
Definition: AbstractRenderable.php:370
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$configurationManager
‪TYPO3 CMS Extbase Configuration ConfigurationManagerInterface $configurationManager
Definition: FormRuntime.php:163
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\FormSession
Definition: FormSession.php:29
‪TYPO3\CMS\Form\Domain\Runtime
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getElementValue
‪mixed getElementValue(string $identifier)
Definition: FormRuntime.php:991
‪TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable\getIdentifier
‪string getIdentifier()
Definition: AbstractRenderable.php:105
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:179
‪TYPO3\CMS\Form\Exception
Definition: Exception.php:24
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormState
‪FormState null getFormState()
Definition: FormRuntime.php:1012
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\triggerAfterFormStateInitialized
‪triggerAfterFormStateInitialized()
Definition: FormRuntime.php:269
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeCurrentPageFromRequest
‪initializeCurrentPageFromRequest()
Definition: FormRuntime.php:282
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$hashService
‪TYPO3 CMS Extbase Security Cryptography HashService $hashService
Definition: FormRuntime.php:147
‪TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface
Definition: FormElementInterface.php:36
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentPage
‪Page null getCurrentPage()
Definition: FormRuntime.php:799
‪TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface
Definition: RootRenderableInterface.php:27
‪TYPO3\CMS\Extbase\Mvc\Web\Response
Definition: Response.php:25
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\setCurrentSiteLanguage
‪setCurrentSiteLanguage(SiteLanguage $currentSiteLanguage)
Definition: FormRuntime.php:1086
‪$validator
‪if(isset($args['d'])) $validator
Definition: validateRstFiles.php:218
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRequest
‪Request getRequest()
Definition: FormRuntime.php:753
‪TYPO3\CMS\Extbase\Mvc\Request\getArguments
‪array getArguments()
Definition: Request.php:382
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentFinisher
‪FinisherInterface null getCurrentFinisher()
Definition: FormRuntime.php:1136
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentFinisher
‪TYPO3 CMS Form Domain Finishers FinisherInterface $currentFinisher
Definition: FormRuntime.php:159
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\processVariants
‪processVariants()
Definition: FormRuntime.php:482
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:35
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\setHoneypotNameInSession
‪setHoneypotNameInSession(Page $page, string $honeypotName)
Definition: FormRuntime.php:452
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\renderHoneypot
‪renderHoneypot()
Definition: FormRuntime.php:385
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isRenderedCached
‪bool isRenderedCached()
Definition: FormRuntime.php:535
‪TYPO3\CMS\Extbase\Mvc\Web\Request
Definition: Request.php:21
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentPage
‪TYPO3 CMS Form Domain Model FormElements Page $currentPage
Definition: FormRuntime.php:136
‪TYPO3\CMS\Extbase\Security\Exception\InvalidHashException
Definition: InvalidHashException.php:21
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getTemplateName
‪string getTemplateName()
Definition: FormRuntime.php:1053
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getResponse
‪Response getResponse()
Definition: FormRuntime.php:766
‪TYPO3\CMS\Form\Domain\Finishers\FinisherContext
Definition: FinisherContext.php:34
‪$output
‪$output
Definition: annotationChecker.php:113
‪TYPO3\CMS\Form\Domain\Model\FormDefinition
Definition: FormDefinition.php:218
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetExists
‪bool offsetExists($identifier)
Definition: FormRuntime.php:926
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$response
‪TYPO3 CMS Extbase Mvc Web Response $response
Definition: FormRuntime.php:114
‪TYPO3\CMS\Form\Domain\Model\Renderable\VariableRenderableInterface
Definition: VariableRenderableInterface.php:25
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:97
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormSession
‪FormSession null getFormSession()
Definition: FormRuntime.php:789
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectObjectManager
‪injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager)
Definition: FormRuntime.php:178
‪TYPO3\CMS\Core\ExpressionLanguage\Resolver
Definition: Resolver.php:25
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormDefinition
‪FormDefinition getFormDefinition()
Definition: FormRuntime.php:1063
‪TYPO3\CMS\Core\Utility\ArrayUtility\assertAllArrayKeysAreValid
‪static assertAllArrayKeysAreValid(array $arrayToTest, array $allowedArrayKeys)
Definition: ArrayUtility.php:32
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeCurrentSiteLanguage
‪initializeCurrentSiteLanguage()
Definition: FormRuntime.php:1095
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\mapAndValidatePage
‪Result mapAndValidatePage(Page $page)
Definition: FormRuntime.php:571
‪TYPO3\CMS\Extbase\Mvc\Request\setArguments
‪setArguments(array $arguments)
Definition: Request.php:369
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formDefinition
‪TYPO3 CMS Form Domain Model FormDefinition $formDefinition
Definition: FormRuntime.php:106
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectConfigurationManager
‪injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
Definition: FormRuntime.php:186
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\setKey
‪setKey($type, $key, $data)
Definition: FrontendUserAuthentication.php:524
‪TYPO3\CMS\Form\Domain\Exception\RenderingException
Definition: RenderingException.php:26
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:91
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$objectManager
‪TYPO3 CMS Extbase Object ObjectManagerInterface $objectManager
Definition: FormRuntime.php:102
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\userWentBackToPreviousStep
‪bool userWentBackToPreviousStep()
Definition: FormRuntime.php:561
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\__construct
‪__construct(FormDefinition $formDefinition, Request $request, Response $response)
Definition: FormRuntime.php:196
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetGet
‪mixed offsetGet($identifier)
Definition: FormRuntime.php:954
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:28
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentSiteLanguage
‪SiteLanguage $currentSiteLanguage
Definition: FormRuntime.php:153
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getIdentifier
‪string getIdentifier()
Definition: FormRuntime.php:740
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeObject
‪initializeObject()
Definition: FormRuntime.php:212
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPreviousEnabledPage
‪Page null getPreviousEnabledPage()
Definition: FormRuntime.php:838
‪TYPO3\CMS\Form\Domain\Model\FormDefinition\getPageByIndex
‪Page getPageByIndex(int $index)
Definition: FormDefinition.php:467
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetUnset
‪offsetUnset($identifier)
Definition: FormRuntime.php:980
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\render
‪string null render()
Definition: FormRuntime.php:675
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getKey
‪mixed getKey($type, $key)
Definition: FrontendUserAuthentication.php:497