‪TYPO3CMS  10.4
FormRuntime.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 /*
19  * Inspired by and partially taken from the Neos.Form package (www.neos.io)
20  */
21 
23 
24 use Psr\Http\Message\ServerRequestInterface;
58 use ‪TYPO3\CMS\Form\Exception as FormException;
63 
102 class ‪FormRuntime implements ‪RootRenderableInterface, \ArrayAccess
103 {
104  const ‪HONEYPOT_NAME_SESSION_IDENTIFIER = 'tx_form_honeypot_name_';
105 
109  protected ‪$objectManager;
110 
114  protected ‪$formDefinition;
115 
119  protected ‪$request;
120 
124  protected ‪$response;
125 
129  protected ‪$formState;
130 
137  protected ‪$formSession;
138 
149  protected ‪$currentPage;
150 
157  protected ‪$lastDisplayedPage;
158 
162  protected ‪$hashService;
163 
170 
176  protected ‪$currentFinisher;
177 
181  protected ‪$configurationManager;
182 
188  {
189  $this->hashService = ‪$hashService;
190  }
191 
197  {
198  $this->objectManager = ‪$objectManager;
199  }
200 
204  public function ‪injectConfigurationManager(ConfigurationManagerInterface ‪$configurationManager)
205  {
206  $this->configurationManager = ‪$configurationManager;
207  }
208 
214  public function ‪__construct(FormDefinition ‪$formDefinition, Request ‪$request, Response ‪$response)
215  {
216  $this->formDefinition = ‪$formDefinition;
217  $arguments = ‪$request->‪getArguments();
218  $this->request = clone ‪$request;
219  $formIdentifier = $this->formDefinition->getIdentifier();
220  if (isset($arguments[$formIdentifier])) {
221  $this->request->‪setArguments($arguments[$formIdentifier]);
222  }
223 
224  $this->response = ‪$response;
225  }
226 
230  public function ‪initializeObject()
231  {
236  $this->‪processVariants();
239 
240  // Only validate and set form values within the form state
241  // if the current request is not the very first request
242  // and the current request can be processed (POST request and uncached).
243  if (!$this->‪isFirstRequest() && $this->‪canProcessFormSubmission()) {
245  }
246 
247  $this->‪renderHoneypot();
248  }
249 
253  protected function ‪initializeFormSessionFromRequest(): void
254  {
255  // Initialize the form session only if the current request can be processed
256  // (POST request and uncached) to ensure unique sessions for each form submitter.
258  return;
259  }
260 
261  $sessionIdentifierFromRequest = $this->request->getInternalArgument('__session');
262  $this->formSession = GeneralUtility::makeInstance(FormSession::class, $sessionIdentifierFromRequest);
263  }
264 
269  protected function ‪initializeFormStateFromRequest()
270  {
271  // Only try to reconstitute the form state if the current request
272  // is not the very first request and if the current request can
273  // be processed (POST request and uncached).
274  $serializedFormStateWithHmac = $this->request->getInternalArgument('__state');
275  if ($serializedFormStateWithHmac === null || !$this->‪canProcessFormSubmission()) {
276  $this->formState = GeneralUtility::makeInstance(FormState::class);
277  } else {
278  try {
279  $serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac);
280  } catch (InvalidHashException | InvalidArgumentForHashGenerationException $e) {
281  throw new BadRequestException('The HMAC of the form state could not be validated.', 1581862823);
282  }
283  $this->formState = unserialize(base64_decode($serializedFormState));
284  }
285  }
286 
287  protected function ‪triggerAfterFormStateInitialized(): void
288  {
289  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterFormStateInitialized'] ?? [] as $className) {
290  $hookObj = GeneralUtility::makeInstance($className);
291  if ($hookObj instanceof ‪AfterFormStateInitializedInterface) {
292  $hookObj->afterFormStateInitialized($this);
293  }
294  }
295  }
296 
300  protected function ‪initializeCurrentPageFromRequest()
301  {
302  // If there was no previous form submissions or if the current request
303  // can't be processed (no POST request and/or cached) then display the first
304  // form step
305  if (!$this->formState->isFormSubmitted() || !$this->canProcessFormSubmission()) {
306  $this->currentPage = $this->formDefinition->getPageByIndex(0);
307 
308  if (!$this->currentPage->isEnabled()) {
309  throw new FormException('Disabling the first page is not allowed', 1527186844);
310  }
311 
312  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterInitializeCurrentPage'] ?? [] as $className) {
313  $hookObj = GeneralUtility::makeInstance($className);
314  if (method_exists($hookObj, 'afterInitializeCurrentPage')) {
315  $this->currentPage = $hookObj->afterInitializeCurrentPage(
316  $this,
317  $this->currentPage,
318  null,
319  $this->request->getArguments()
320  );
321  }
322  }
323  return;
324  }
325 
326  $this->lastDisplayedPage = $this->formDefinition->getPageByIndex($this->formState->getLastDisplayedPageIndex());
327  $currentPageIndex = (int)$this->request->getInternalArgument('__currentPage');
328 
329  if ($this->‪userWentBackToPreviousStep()) {
330  if ($currentPageIndex < $this->lastDisplayedPage->getIndex()) {
331  $currentPageIndex = $this->lastDisplayedPage->getIndex();
332  }
333  } else {
334  if ($currentPageIndex > $this->lastDisplayedPage->getIndex() + 1) {
335  $currentPageIndex = $this->lastDisplayedPage->getIndex() + 1;
336  }
337  }
338 
339  if ($currentPageIndex >= count($this->formDefinition->getPages())) {
340  // Last Page
341  $this->currentPage = null;
342  } else {
343  $this->currentPage = $this->formDefinition->getPageByIndex($currentPageIndex);
344 
345  if (!$this->currentPage->isEnabled()) {
346  if ($currentPageIndex === 0) {
347  throw new FormException('Disabling the first page is not allowed', 1527186845);
348  }
349 
350  if ($this->‪userWentBackToPreviousStep()) {
351  $this->currentPage = $this->‪getPreviousEnabledPage();
352  } else {
353  $this->currentPage = $this->‪getNextEnabledPage();
354  }
355  }
356  }
357 
358  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterInitializeCurrentPage'] ?? [] as $className) {
359  $hookObj = GeneralUtility::makeInstance($className);
360  if (method_exists($hookObj, 'afterInitializeCurrentPage')) {
361  $this->currentPage = $hookObj->afterInitializeCurrentPage(
362  $this,
363  $this->currentPage,
364  $this->lastDisplayedPage,
365  $this->request->getArguments()
366  );
367  }
368  }
369  }
370 
374  protected function ‪initializeHoneypotFromRequest()
375  {
376  $renderingOptions = $this->formDefinition->getRenderingOptions();
377  if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') {
378  return;
379  }
380 
381  ‪ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']);
382 
383  if (!$this->‪isFirstRequest()) {
384  $elementsCount = count($this->lastDisplayedPage->getElements());
385  if ($elementsCount === 0) {
386  return;
387  }
388 
389  $honeypotNameFromSession = $this->‪getHoneypotNameFromSession($this->lastDisplayedPage);
390  if ($honeypotNameFromSession) {
391  $honeypotElement = $this->lastDisplayedPage->createElement($honeypotNameFromSession, $renderingOptions['honeypot']['formElementToUse']);
392  ‪$validator = $this->objectManager->get(EmptyValidator::class);
393  $honeypotElement->addValidator(‪$validator);
394  }
395  }
396  }
397 
401  protected function ‪renderHoneypot()
402  {
403  $renderingOptions = $this->formDefinition->getRenderingOptions();
404  if (!isset($renderingOptions['honeypot']['enable']) || $renderingOptions['honeypot']['enable'] === false || TYPO3_MODE === 'BE') {
405  return;
406  }
407 
408  ‪ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']);
409 
410  if (!$this->‪isAfterLastPage()) {
411  $elementsCount = count($this->currentPage->getElements());
412  if ($elementsCount === 0) {
413  return;
414  }
415 
416  if (!$this->‪isFirstRequest()) {
417  $honeypotNameFromSession = $this->‪getHoneypotNameFromSession($this->lastDisplayedPage);
418  if ($honeypotNameFromSession) {
419  $honeypotElement = $this->formDefinition->getElementByIdentifier($honeypotNameFromSession);
420  if ($honeypotElement instanceof FormElementInterface) {
421  $this->lastDisplayedPage->removeElement($honeypotElement);
422  }
423  }
424  }
425 
426  $elementsCount = count($this->currentPage->getElements());
427  $randomElementNumber = random_int(0, $elementsCount - 1);
428  $honeypotName = substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, random_int(5, 26));
429 
430  $referenceElement = $this->currentPage->getElements()[$randomElementNumber];
431  $honeypotElement = $this->currentPage->createElement($honeypotName, $renderingOptions['honeypot']['formElementToUse']);
432  ‪$validator = $this->objectManager->get(EmptyValidator::class);
433 
434  $honeypotElement->addValidator(‪$validator);
435  if (random_int(0, 1) === 1) {
436  $this->currentPage->moveElementAfter($honeypotElement, $referenceElement);
437  } else {
438  $this->currentPage->moveElementBefore($honeypotElement, $referenceElement);
439  }
440  $this->‪setHoneypotNameInSession($this->currentPage, $honeypotName);
441  }
442  }
443 
448  protected function ‪getHoneypotNameFromSession(Page $page)
449  {
450  if ($this->‪isFrontendUserAuthenticated()) {
451  $honeypotNameFromSession = $this->‪getFrontendUser()->‪getKey(
452  'user',
453  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier()
454  );
455  } else {
456  $honeypotNameFromSession = $this->‪getFrontendUser()->‪getKey(
457  'ses',
458  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier()
459  );
460  }
461  return $honeypotNameFromSession;
462  }
463 
468  protected function ‪setHoneypotNameInSession(Page $page, string $honeypotName)
469  {
470  if ($this->‪isFrontendUserAuthenticated()) {
471  $this->‪getFrontendUser()->‪setKey(
472  'user',
473  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier(),
474  $honeypotName
475  );
476  } else {
477  $this->‪getFrontendUser()->‪setKey(
478  'ses',
479  self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->‪getIdentifier() . $page->getIdentifier(),
480  $honeypotName
481  );
482  }
483  }
484 
490  protected function ‪isFrontendUserAuthenticated(): bool
491  {
492  return (bool)GeneralUtility::makeInstance(Context::class)
493  ->getPropertyFromAspect('frontend.user', 'isLoggedIn', false);
494  }
495 
496  protected function ‪processVariants()
497  {
498  $conditionResolver = $this->‪getConditionResolver();
499 
500  $renderables = array_merge([$this->formDefinition], $this->formDefinition->getRenderablesRecursively());
501  foreach ($renderables as $renderable) {
502  if ($renderable instanceof ‪VariableRenderableInterface) {
503  $variants = $renderable->getVariants();
504  foreach ($variants as $variant) {
505  if ($variant->conditionMatches($conditionResolver)) {
506  $variant->apply();
507  }
508  }
509  }
510  }
511  }
512 
518  protected function ‪isAfterLastPage(): bool
519  {
520  return $this->currentPage === null;
521  }
522 
528  protected function ‪isFirstRequest(): bool
529  {
530  return $this->lastDisplayedPage === null;
531  }
532 
536  protected function ‪isPostRequest(): bool
537  {
538  return $this->‪getRequest()->‪getMethod() === 'POST';
539  }
540 
550  protected function ‪isRenderedCached(): bool
551  {
552  $contentObject = $this->configurationManager->getContentObject();
553  return $contentObject === null
554  ? true
555  // @todo this does not work when rendering a cached `FLUIDTEMPLATE` (not nested in `COA_INT`)
556  : $contentObject->getUserObjectType() === ‪ContentObjectRenderer::OBJECTTYPE_USER;
557  }
558 
562  protected function ‪processSubmittedFormValues()
563  {
564  $result = $this->‪mapAndValidatePage($this->lastDisplayedPage);
565  if ($result->hasErrors() && !$this->userWentBackToPreviousStep()) {
566  $this->currentPage = ‪$this->lastDisplayedPage;
567  $this->request->setOriginalRequestMappingResults($result);
568  }
569  }
570 
576  protected function ‪userWentBackToPreviousStep(): bool
577  {
578  return !$this->‪isAfterLastPage() && !$this->‪isFirstRequest() && $this->currentPage->getIndex() < $this->lastDisplayedPage->getIndex();
579  }
580 
586  protected function ‪mapAndValidatePage(Page $page): Result
587  {
588  $result = $this->objectManager->get(Result::class);
589  $requestArguments = $this->request->getArguments();
590 
591  $propertyPathsForWhichPropertyMappingShouldHappen = [];
592  $registerPropertyPaths = function ($propertyPath) use (&$propertyPathsForWhichPropertyMappingShouldHappen) {
593  $propertyPathParts = explode('.', $propertyPath);
594  $accumulatedPropertyPathParts = [];
595  foreach ($propertyPathParts as $propertyPathPart) {
596  $accumulatedPropertyPathParts[] = $propertyPathPart;
597  $temporaryPropertyPath = implode('.', $accumulatedPropertyPathParts);
598  $propertyPathsForWhichPropertyMappingShouldHappen[$temporaryPropertyPath] = $temporaryPropertyPath;
599  }
600  };
601 
602  $value = null;
603 
604  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterSubmit'] ?? [] as $className) {
605  $hookObj = GeneralUtility::makeInstance($className);
606  if (method_exists($hookObj, 'afterSubmit')) {
607  $value = $hookObj->afterSubmit(
608  $this,
609  $page,
610  $value,
611  $requestArguments
612  );
613  }
614  }
615 
616  foreach ($page->getElementsRecursively() as $element) {
617  if (!$element->isEnabled()) {
618  continue;
619  }
620 
621  try {
622  $value = ‪ArrayUtility::getValueByPath($requestArguments, $element->getIdentifier(), '.');
623  } catch (MissingArrayPathException $exception) {
624  $value = null;
625  }
626 
627  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['afterSubmit'] ?? [] as $className) {
628  $hookObj = GeneralUtility::makeInstance($className);
629  if (method_exists($hookObj, 'afterSubmit')) {
630  $value = $hookObj->afterSubmit(
631  $this,
632  $element,
633  $value,
634  $requestArguments
635  );
636  }
637  }
638 
639  $this->formState->setFormValue($element->getIdentifier(), $value);
640  $registerPropertyPaths($element->getIdentifier());
641  }
642 
643  // The more parts the path has, the more early it is processed
644  usort($propertyPathsForWhichPropertyMappingShouldHappen, function ($a, $b) {
645  return substr_count($b, '.') - substr_count($a, '.');
646  });
647 
648  $processingRules = $this->formDefinition->getProcessingRules();
649 
650  foreach ($propertyPathsForWhichPropertyMappingShouldHappen as $propertyPath) {
651  if (isset($processingRules[$propertyPath])) {
652  $processingRule = $processingRules[$propertyPath];
653  $value = $this->formState->getFormValue($propertyPath);
654  try {
655  $value = $processingRule->process($value);
656  } catch (‪PropertyException $exception) {
657  throw new PropertyMappingException(
658  'Failed to process FormValue at "' . $propertyPath . '" from "' . gettype($value) . '" to "' . $processingRule->getDataType() . '"',
659  1480024933,
660  $exception
661  );
662  }
663  $result->forProperty($this->‪getIdentifier() . '.' . $propertyPath)->merge($processingRule->getProcessingMessages());
664  $this->formState->setFormValue($propertyPath, $value);
665  }
666  }
667 
668  return $result;
669  }
670 
679  public function ‪overrideCurrentPage(int $pageIndex)
680  {
681  $this->currentPage = $this->formDefinition->getPageByIndex($pageIndex);
682  }
683 
690  public function ‪render()
691  {
692  if ($this->‪isAfterLastPage()) {
693  return $this->‪invokeFinishers();
694  }
695  $this->‪processVariants();
696 
697  $this->formState->setLastDisplayedPageIndex($this->currentPage->getIndex());
698 
699  if ($this->formDefinition->getRendererClassName() === '') {
700  throw new RenderingException(sprintf('The form definition "%s" does not have a rendererClassName set.', $this->formDefinition->getIdentifier()), 1326095912);
701  }
702  $rendererClassName = $this->formDefinition->getRendererClassName();
703  $renderer = $this->objectManager->get($rendererClassName);
704  if (!($renderer instanceof RendererInterface)) {
705  throw new RenderingException(sprintf('The renderer "%s" des not implement RendererInterface', $rendererClassName), 1326096024);
706  }
707 
708  $controllerContext = $this->‪getControllerContext();
709 
710  $renderer->setControllerContext($controllerContext);
711  $renderer->setFormRuntime($this);
712  return $renderer->render();
713  }
714 
720  protected function ‪invokeFinishers(): string
721  {
722  $finisherContext = $this->objectManager->get(
723  FinisherContext::class,
724  $this,
725  $this->‪getControllerContext()
726  );
727 
728  ‪$output = '';
729  $originalContent = $this->response->getContent();
730  $this->response->setContent(null);
731  foreach ($this->formDefinition->getFinishers() as $finisher) {
732  $this->currentFinisher = $finisher;
733  $this->‪processVariants();
734 
735  $finisherOutput = $finisher->execute($finisherContext);
736  if (is_string($finisherOutput) && !empty($finisherOutput)) {
737  ‪$output .= $finisherOutput;
738  } else {
739  ‪$output .= $this->response->getContent();
740  $this->response->setContent(null);
741  }
742 
743  if ($finisherContext->isCancelled()) {
744  break;
745  }
746  }
747  $this->response->setContent($originalContent);
748 
749  return ‪$output;
750  }
751 
755  public function ‪getIdentifier(): string
756  {
757  return $this->formDefinition->getIdentifier();
758  }
759 
768  public function ‪getRequest(): ‪Request
769  {
770  return ‪$this->request;
771  }
772 
781  public function ‪getResponse(): ‪Response
782  {
784  }
785 
795  public function ‪canProcessFormSubmission(): bool
796  {
797  return $this->‪isPostRequest() && !$this->‪isRenderedCached();
798  }
799 
804  public function ‪getFormSession(): ?FormSession
805  {
806  return ‪$this->formSession;
807  }
808 
814  public function ‪getCurrentPage(): ?Page
815  {
816  return ‪$this->currentPage;
817  }
818 
824  public function ‪getPreviousPage(): ?Page
825  {
826  $previousPageIndex = $this->currentPage->getIndex() - 1;
827  if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) {
828  return $this->formDefinition->getPageByIndex($previousPageIndex);
829  }
830  return null;
831  }
832 
838  public function ‪getNextPage(): ?Page
839  {
840  $nextPageIndex = $this->currentPage->getIndex() + 1;
841  if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) {
842  return $this->formDefinition->getPageByIndex($nextPageIndex);
843  }
844  return null;
845  }
846 
853  public function ‪getPreviousEnabledPage(): ?Page
854  {
855  $previousPage = null;
856  $previousPageIndex = $this->currentPage->getIndex() - 1;
857  while ($previousPageIndex >= 0) {
858  if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) {
859  $previousPage = $this->formDefinition->getPageByIndex($previousPageIndex);
860 
861  if ($previousPage->isEnabled()) {
862  break;
863  }
864 
865  $previousPage = null;
866  $previousPageIndex--;
867  } else {
868  $previousPage = null;
869  break;
870  }
871  }
872 
873  return $previousPage;
874  }
875 
882  public function ‪getNextEnabledPage(): ?Page
883  {
884  $nextPage = null;
885  $pageCount = count($this->formDefinition->getPages());
886  $nextPageIndex = $this->currentPage->getIndex() + 1;
887 
888  while ($nextPageIndex < $pageCount) {
889  if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) {
890  $nextPage = $this->formDefinition->getPageByIndex($nextPageIndex);
891  $renderingOptions = $nextPage->getRenderingOptions();
892  if (
893  !isset($renderingOptions['enabled'])
894  || (bool)$renderingOptions['enabled']
895  ) {
896  break;
897  }
898  $nextPage = null;
899  $nextPageIndex++;
900  } else {
901  $nextPage = null;
902  break;
903  }
904  }
905 
906  return $nextPage;
907  }
908 
912  protected function ‪getControllerContext(): ControllerContext
913  {
914  $uriBuilder = $this->objectManager->get(UriBuilder::class);
915  $uriBuilder->setRequest($this->request);
916  $controllerContext = $this->objectManager->get(ControllerContext::class);
917  $controllerContext->setRequest($this->request);
918  $controllerContext->setResponse($this->response);
919  $controllerContext->setArguments($this->objectManager->get(Arguments::class, []));
920  $controllerContext->setUriBuilder($uriBuilder);
921  return $controllerContext;
922  }
923 
931  public function ‪getType(): string
932  {
933  return $this->formDefinition->getType();
934  }
935 
941  public function ‪offsetExists($identifier)
942  {
943  if ($this->‪getElementValue($identifier) !== null) {
944  return true;
945  }
946 
947  if (is_callable([$this, 'get' . ucfirst($identifier)])) {
948  return true;
949  }
950  if (is_callable([$this, 'has' . ucfirst($identifier)])) {
951  return true;
952  }
953  if (is_callable([$this, 'is' . ucfirst($identifier)])) {
954  return true;
955  }
956  if (property_exists($this, $identifier)) {
957  $propertyReflection = new \ReflectionProperty($this, $identifier);
958  return $propertyReflection->isPublic();
959  }
960 
961  return false;
962  }
963 
969  public function ‪offsetGet($identifier)
970  {
971  if ($this->‪getElementValue($identifier) !== null) {
972  return $this->‪getElementValue($identifier);
973  }
974  $getterMethodName = 'get' . ucfirst($identifier);
975  if (is_callable([$this, $getterMethodName])) {
976  return $this->{$getterMethodName}();
977  }
978  return null;
979  }
980 
986  public function ‪offsetSet($identifier, $value)
987  {
988  $this->formState->setFormValue($identifier, $value);
989  }
990 
995  public function ‪offsetUnset($identifier)
996  {
997  $this->formState->setFormValue($identifier, null);
998  }
999 
1006  public function ‪getElementValue(string $identifier)
1007  {
1008  $formValue = $this->formState->getFormValue($identifier);
1009  if ($formValue !== null) {
1010  return $formValue;
1011  }
1012  return $this->formDefinition->getElementDefaultValueByIdentifier($identifier);
1013  }
1014 
1018  public function ‪getPages(): array
1019  {
1020  return $this->formDefinition->getPages();
1021  }
1022 
1027  public function ‪getFormState(): ?FormState
1028  {
1029  return ‪$this->formState;
1030  }
1031 
1037  public function ‪getRenderingOptions(): array
1038  {
1039  return $this->formDefinition->getRenderingOptions();
1040  }
1041 
1048  public function ‪getRendererClassName(): string
1049  {
1050  return $this->formDefinition->getRendererClassName();
1051  }
1052 
1058  public function ‪getLabel(): string
1059  {
1060  return $this->formDefinition->getLabel();
1061  }
1062 
1068  public function ‪getTemplateName(): string
1069  {
1070  return $this->formDefinition->getTemplateName();
1071  }
1072 
1078  public function ‪getFormDefinition(): FormDefinition
1079  {
1080  return ‪$this->formDefinition;
1081  }
1082 
1088  public function ‪getCurrentSiteLanguage(): ?SiteLanguage
1089  {
1091  }
1092 
1102  {
1103  $this->currentSiteLanguage = ‪$currentSiteLanguage;
1104  }
1105 
1110  protected function ‪initializeCurrentSiteLanguage(): void
1111  {
1112  if (
1113  ‪$GLOBALS['TYPO3_REQUEST'] instanceof ServerRequestInterface
1114  && ‪$GLOBALS['TYPO3_REQUEST']->getAttribute('language') instanceof SiteLanguage
1115  ) {
1116  $this->currentSiteLanguage = ‪$GLOBALS['TYPO3_REQUEST']->getAttribute('language');
1117  } else {
1118  $pageId = 0;
1119  $languageId = (int)GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('language', 'id', 0);
1120 
1121  if ($this->‪getTypoScriptFrontendController() !== null) {
1122  $pageId = $this->‪getTypoScriptFrontendController()->id;
1123  }
1124 
1125  $fakeSiteConfiguration = [
1126  'languages' => [
1127  [
1128  'languageId' => $languageId,
1129  'title' => 'Dummy',
1130  'navigationTitle' => '',
1131  'typo3Language' => '',
1132  'flag' => '',
1133  'locale' => '',
1134  'iso-639-1' => '',
1135  'hreflang' => '',
1136  'direction' => '',
1137  ],
1138  ],
1139  ];
1140 
1141  $this->currentSiteLanguage = GeneralUtility::makeInstance(Site::class, 'form-dummy', $pageId, $fakeSiteConfiguration)
1142  ->getLanguageById($languageId);
1143  }
1144  }
1145 
1151  public function ‪getCurrentFinisher(): ?FinisherInterface
1152  {
1154  }
1155 
1159  protected function ‪getConditionResolver(): Resolver
1160  {
1161  $formValues = array_replace_recursive(
1162  $this->‪getFormState()->getFormValues(),
1163  $this->‪getRequest()->getArguments()
1164  );
1165  $page = $this->‪getCurrentPage() ?? $this->‪getFormDefinition()->‪getPageByIndex(0);
1166 
1167  $finisherIdentifier = '';
1168  if ($this->‪getCurrentFinisher() !== null) {
1169  if (method_exists($this->‪getCurrentFinisher(), 'getFinisherIdentifier')) {
1170  $finisherIdentifier = $this->‪getCurrentFinisher()->getFinisherIdentifier();
1171  } else {
1172  $finisherIdentifier = (new \ReflectionClass($this->‪getCurrentFinisher()))->getShortName();
1173  $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier);
1174  }
1175  }
1176 
1177  return GeneralUtility::makeInstance(
1178  Resolver::class,
1179  'form',
1180  [
1181  // some shortcuts
1182  'formRuntime' => $this,
1183  'formValues' => $formValues,
1184  'stepIdentifier' => $page->getIdentifier(),
1185  'stepType' => $page->getType(),
1186  'finisherIdentifier' => $finisherIdentifier,
1187  ],
1188  ‪$GLOBALS['TYPO3_REQUEST'] ?? GeneralUtility::makeInstance(ServerRequest::class)
1189  );
1190  }
1196  {
1197  return $this->‪getTypoScriptFrontendController()->fe_user;
1198  }
1199 
1204  {
1205  return ‪$GLOBALS['TSFE'] ?? null;
1206  }
1207 }
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isAfterLastPage
‪bool isAfterLastPage()
Definition: FormRuntime.php:506
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPreviousPage
‪Page null getPreviousPage()
Definition: FormRuntime.php:812
‪TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection\getElementsRecursively
‪FormElementInterface[] getElementsRecursively()
Definition: AbstractSection.php:78
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formState
‪TYPO3 CMS Form Domain Runtime FormState $formState
Definition: FormRuntime.php:124
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime
Definition: FormRuntime.php:103
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\overrideCurrentPage
‪overrideCurrentPage(int $pageIndex)
Definition: FormRuntime.php:667
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\HONEYPOT_NAME_SESSION_IDENTIFIER
‪const HONEYPOT_NAME_SESSION_IDENTIFIER
Definition: FormRuntime.php:104
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\OBJECTTYPE_USER
‪const OBJECTTYPE_USER
Definition: ContentObjectRenderer.php:436
‪TYPO3\CMS\Form\Mvc\Validation\EmptyValidator
Definition: EmptyValidator.php:28
‪TYPO3\CMS\Extbase\Property\Exception
Definition: DuplicateObjectException.php:18
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$request
‪TYPO3 CMS Extbase Mvc Web Request $request
Definition: FormRuntime.php:116
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRenderingOptions
‪array getRenderingOptions()
Definition: FormRuntime.php:1025
‪TYPO3\CMS\Form\Domain\Finishers\FinisherInterface
Definition: FinisherInterface.php:31
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isFirstRequest
‪bool isFirstRequest()
Definition: FormRuntime.php:516
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getTypoScriptFrontendController
‪TypoScriptFrontendController null getTypoScriptFrontendController()
Definition: FormRuntime.php:1191
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isPostRequest
‪bool isPostRequest()
Definition: FormRuntime.php:524
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFrontendUser
‪FrontendUserAuthentication getFrontendUser()
Definition: FormRuntime.php:1183
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getHoneypotNameFromSession
‪string null getHoneypotNameFromSession(Page $page)
Definition: FormRuntime.php:436
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$lastDisplayedPage
‪TYPO3 CMS Form Domain Model FormElements Page $lastDisplayedPage
Definition: FormRuntime.php:149
‪TYPO3\CMS\Form\Domain\Runtime\Exception\PropertyMappingException
Definition: PropertyMappingException.php:28
‪TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder
Definition: UriBuilder.php:39
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeFormSessionFromRequest
‪initializeFormSessionFromRequest()
Definition: FormRuntime.php:241
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getControllerContext
‪ControllerContext getControllerContext()
Definition: FormRuntime.php:900
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:28
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentSiteLanguage
‪SiteLanguage getCurrentSiteLanguage()
Definition: FormRuntime.php:1076
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isFrontendUserAuthenticated
‪bool isFrontendUserAuthenticated()
Definition: FormRuntime.php:478
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formSession
‪FormSession null $formSession
Definition: FormRuntime.php:131
‪TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext
Definition: ControllerContext.php:28
‪TYPO3\CMS\Form\Domain\Renderer\RendererInterface
Definition: RendererInterface.php:35
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeHoneypotFromRequest
‪initializeHoneypotFromRequest()
Definition: FormRuntime.php:362
‪TYPO3\CMS\Form\Domain\Runtime\FormState
Definition: FormState.php:36
‪TYPO3\CMS\Extbase\Mvc\Controller\Arguments
Definition: Arguments.php:27
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\canProcessFormSubmission
‪bool canProcessFormSubmission()
Definition: FormRuntime.php:783
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getNextEnabledPage
‪Page null getNextEnabledPage()
Definition: FormRuntime.php:870
‪TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:28
‪TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
Definition: InvalidArgumentForHashGenerationException.php:26
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\invokeFinishers
‪string invokeFinishers()
Definition: FormRuntime.php:708
‪TYPO3\CMS\Core\Error\Http\BadRequestException
Definition: BadRequestException.php:24
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetSet
‪offsetSet($identifier, $value)
Definition: FormRuntime.php:974
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getNextPage
‪Page null getNextPage()
Definition: FormRuntime.php:826
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRendererClassName
‪string getRendererClassName()
Definition: FormRuntime.php:1036
‪TYPO3\CMS\Extbase\Security\Cryptography\HashService
Definition: HashService.php:31
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getConditionResolver
‪Resolver getConditionResolver()
Definition: FormRuntime.php:1147
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\Lifecycle\AfterFormStateInitializedInterface
Definition: AfterFormStateInitializedInterface.php:29
‪TYPO3\CMS\Extbase\Error\Result
Definition: Result.php:24
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\processSubmittedFormValues
‪processSubmittedFormValues()
Definition: FormRuntime.php:550
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getLabel
‪string getLabel()
Definition: FormRuntime.php:1046
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getType
‪string getType()
Definition: FormRuntime.php:919
‪TYPO3\CMS\Extbase\Object\ObjectManagerInterface
Definition: ObjectManagerInterface.php:26
‪TYPO3\CMS\Form\Domain\Model\FormElements\Page
Definition: Page.php:44
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:40
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeFormStateFromRequest
‪initializeFormStateFromRequest()
Definition: FormRuntime.php:257
‪TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable\getIndex
‪int getIndex()
Definition: AbstractRenderable.php:375
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPages
‪array Page[] getPages()
Definition: FormRuntime.php:1006
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$configurationManager
‪TYPO3 CMS Extbase Configuration ConfigurationManagerInterface $configurationManager
Definition: FormRuntime.php:169
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\FormSession
Definition: FormSession.php:31
‪TYPO3\CMS\Form\Domain\Runtime
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getElementValue
‪mixed getElementValue(string $identifier)
Definition: FormRuntime.php:994
‪TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable\getIdentifier
‪string getIdentifier()
Definition: AbstractRenderable.php:109
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:180
‪TYPO3\CMS\Form\Exception
Definition: Exception.php:26
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormState
‪FormState null getFormState()
Definition: FormRuntime.php:1015
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\triggerAfterFormStateInitialized
‪triggerAfterFormStateInitialized()
Definition: FormRuntime.php:275
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeCurrentPageFromRequest
‪initializeCurrentPageFromRequest()
Definition: FormRuntime.php:288
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$hashService
‪TYPO3 CMS Extbase Security Cryptography HashService $hashService
Definition: FormRuntime.php:153
‪TYPO3\CMS\Form\Domain\Model\FormElements\FormElementInterface
Definition: FormElementInterface.php:40
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentPage
‪Page null getCurrentPage()
Definition: FormRuntime.php:802
‪TYPO3\CMS\Form\Domain\Model\Renderable\RootRenderableInterface
Definition: RootRenderableInterface.php:31
‪TYPO3\CMS\Extbase\Mvc\Web\Response
Definition: Response.php:26
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\setCurrentSiteLanguage
‪setCurrentSiteLanguage(SiteLanguage $currentSiteLanguage)
Definition: FormRuntime.php:1089
‪$validator
‪if(isset($args['d'])) $validator
Definition: validateRstFiles.php:218
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getRequest
‪Request getRequest()
Definition: FormRuntime.php:756
‪TYPO3\CMS\Extbase\Mvc\Request\getArguments
‪array getArguments()
Definition: Request.php:378
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getCurrentFinisher
‪FinisherInterface null getCurrentFinisher()
Definition: FormRuntime.php:1139
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentFinisher
‪TYPO3 CMS Form Domain Finishers FinisherInterface $currentFinisher
Definition: FormRuntime.php:165
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\processVariants
‪processVariants()
Definition: FormRuntime.php:484
‪TYPO3\CMS\Core\Http\ServerRequest
Definition: ServerRequest.php:37
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\setHoneypotNameInSession
‪setHoneypotNameInSession(Page $page, string $honeypotName)
Definition: FormRuntime.php:456
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\renderHoneypot
‪renderHoneypot()
Definition: FormRuntime.php:389
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\isRenderedCached
‪bool isRenderedCached()
Definition: FormRuntime.php:538
‪TYPO3\CMS\Extbase\Mvc\Web\Request
Definition: Request.php:23
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentPage
‪TYPO3 CMS Form Domain Model FormElements Page $currentPage
Definition: FormRuntime.php:142
‪TYPO3\CMS\Extbase\Security\Exception\InvalidHashException
Definition: InvalidHashException.php:26
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectObjectManager
‪injectObjectManager(ObjectManagerInterface $objectManager)
Definition: FormRuntime.php:184
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getTemplateName
‪string getTemplateName()
Definition: FormRuntime.php:1056
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getResponse
‪Response getResponse()
Definition: FormRuntime.php:769
‪TYPO3\CMS\Form\Domain\Finishers\FinisherContext
Definition: FinisherContext.php:37
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Form\Domain\Model\FormDefinition
Definition: FormDefinition.php:223
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetExists
‪bool offsetExists($identifier)
Definition: FormRuntime.php:929
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$response
‪TYPO3 CMS Extbase Mvc Web Response $response
Definition: FormRuntime.php:120
‪TYPO3\CMS\Form\Domain\Model\Renderable\VariableRenderableInterface
Definition: VariableRenderableInterface.php:29
‪TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
Definition: TypoScriptFrontendController.php:98
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getFormSession
‪FormSession null getFormSession()
Definition: FormRuntime.php:792
‪TYPO3\CMS\Core\ExpressionLanguage\Resolver
Definition: Resolver.php:27
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪$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:1066
‪TYPO3\CMS\Core\Utility\ArrayUtility\assertAllArrayKeysAreValid
‪static assertAllArrayKeysAreValid(array $arrayToTest, array $allowedArrayKeys)
Definition: ArrayUtility.php:33
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeCurrentSiteLanguage
‪initializeCurrentSiteLanguage()
Definition: FormRuntime.php:1098
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectHashService
‪injectHashService(HashService $hashService)
Definition: FormRuntime.php:175
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\mapAndValidatePage
‪Result mapAndValidatePage(Page $page)
Definition: FormRuntime.php:574
‪TYPO3\CMS\Extbase\Mvc\Request\setArguments
‪setArguments(array $arguments)
Definition: Request.php:365
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$formDefinition
‪TYPO3 CMS Form Domain Model FormDefinition $formDefinition
Definition: FormRuntime.php:112
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\injectConfigurationManager
‪injectConfigurationManager(ConfigurationManagerInterface $configurationManager)
Definition: FormRuntime.php:192
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\setKey
‪setKey($type, $key, $data)
Definition: FrontendUserAuthentication.php:541
‪TYPO3\CMS\Form\Domain\Exception\RenderingException
Definition: RenderingException.php:30
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:97
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$objectManager
‪TYPO3 CMS Extbase Object ObjectManagerInterface $objectManager
Definition: FormRuntime.php:108
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\userWentBackToPreviousStep
‪bool userWentBackToPreviousStep()
Definition: FormRuntime.php:564
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\__construct
‪__construct(FormDefinition $formDefinition, Request $request, Response $response)
Definition: FormRuntime.php:202
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetGet
‪mixed offsetGet($identifier)
Definition: FormRuntime.php:957
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
Definition: FrontendUserAuthentication.php:30
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\$currentSiteLanguage
‪SiteLanguage $currentSiteLanguage
Definition: FormRuntime.php:159
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getIdentifier
‪string getIdentifier()
Definition: FormRuntime.php:743
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\initializeObject
‪initializeObject()
Definition: FormRuntime.php:218
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\getPreviousEnabledPage
‪Page null getPreviousEnabledPage()
Definition: FormRuntime.php:841
‪TYPO3\CMS\Form\Domain\Model\FormDefinition\getPageByIndex
‪Page getPageByIndex(int $index)
Definition: FormDefinition.php:473
‪TYPO3\CMS\Extbase\Mvc\Request\getMethod
‪string getMethod()
Definition: Request.php:522
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\offsetUnset
‪offsetUnset($identifier)
Definition: FormRuntime.php:983
‪TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext\setRequest
‪setRequest(Request $request)
Definition: ControllerContext.php:78
‪TYPO3\CMS\Form\Domain\Runtime\FormRuntime\render
‪string null render()
Definition: FormRuntime.php:678
‪TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication\getKey
‪mixed getKey($type, $key)
Definition: FrontendUserAuthentication.php:513