‪TYPO3CMS  ‪main
FormEditorController.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 
19 
20 use Psr\Http\Message\ResponseInterface;
27 use TYPO3\CMS\Core\Imaging\IconSize;
47 
55 {
56  protected const ‪JS_MODULE_NAMES = ['app', 'mediator', 'viewModel'];
57 
58  protected array ‪$prototypeConfiguration;
59 
60  public function ‪__construct(
61  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
62  protected readonly ‪PageRenderer $pageRenderer,
63  protected readonly ‪IconFactory $iconFactory,
64  protected readonly ‪FormDefinitionConversionService $formDefinitionConversionService,
65  ) {
66  }
67 
73  public function ‪indexAction(string $formPersistenceIdentifier, string $prototypeName = null): ResponseInterface
74  {
75  if (!$this->formPersistenceManager->isAllowedPersistencePath($formPersistenceIdentifier)) {
76  throw new ‪PersistenceManagerException(sprintf('Read "%s" is not allowed', $formPersistenceIdentifier), 1614500662);
77  }
78 
79  if (
80  ‪PathUtility::isExtensionPath($formPersistenceIdentifier)
81  && !$this->formSettings['persistenceManager']['allowSaveToExtensionPaths']
82  ) {
83  throw new ‪PersistenceManagerException('Edit a extension formDefinition is not allowed.', 1478265661);
84  }
85 
86  $configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
87  $formDefinition = $this->formPersistenceManager->load($formPersistenceIdentifier);
88 
89  if ($prototypeName === null) {
90  $prototypeName = $formDefinition['prototypeName'] ?? 'standard';
91  } else {
92  // Loading a form definition with another prototype is currently not implemented but is planned in the future.
93  // This safety check is a preventive measure.
94  $selectablePrototypeNames = $configurationService->getSelectablePrototypeNamesDefinedInFormEditorSetup();
95  if (!in_array($prototypeName, $selectablePrototypeNames, true)) {
96  throw new ‪Exception(sprintf('The prototype name "%s" is not configured within "formManager.selectablePrototypesConfiguration" ', $prototypeName), 1528625039);
97  }
98  }
99 
100  $formDefinition['prototypeName'] = $prototypeName;
101  $this->prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName);
102 
103  $formDefinition = $this->‪transformFormDefinitionForFormEditor($formDefinition);
104  $formEditorDefinitions = $this->‪getFormEditorDefinitions();
105 
106  $additionalViewModelJavaScriptModules = array_map(
107  static fn (string $name) => ‪JavaScriptModuleInstruction::create($name),
108  $this->prototypeConfiguration['formEditor']['dynamicJavaScriptModules']['additionalViewModelModules'] ?? []
109  );
110  array_map($this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(...), $additionalViewModelJavaScriptModules);
111  $formEditorAppInitialData = [
112  'formEditorDefinitions' => $formEditorDefinitions,
113  'formDefinition' => $formDefinition,
114  'formPersistenceIdentifier' => $formPersistenceIdentifier,
115  'prototypeName' => $prototypeName,
116  'endpoints' => [
117  'formPageRenderer' => $this->uriBuilder->uriFor('renderFormPage'),
118  'saveForm' => $this->uriBuilder->uriFor('saveForm'),
119  ],
120  'additionalViewModelModules' => $additionalViewModelJavaScriptModules,
121  'maximumUndoSteps' => $this->prototypeConfiguration['formEditor']['maximumUndoSteps'],
122  ];
123 
124  $moduleTemplate = $this->‪initializeModuleTemplate($this->request);
125  $moduleTemplate->assign('formEditorTemplates', $this->‪renderFormEditorTemplates($formEditorDefinitions));
126 
127  ‪$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
128  $addInlineSettings = [
129  'FormEditor' => [
130  'typo3WinBrowserUrl' => (string)‪$uriBuilder->buildUriFromRoute('wizard_element_browser'),
131  ],
132  ];
133 
134  $addInlineSettings = array_replace_recursive(
135  $addInlineSettings,
136  $this->prototypeConfiguration['formEditor']['addInlineSettings']
137  );
138 
139  if (json_encode($formEditorAppInitialData) === false) {
140  throw new ‪Exception('The form editor app data could not be encoded', 1628677079);
141  }
142 
143  $javaScriptModules = array_map(
144  static fn (string $name) => ‪JavaScriptModuleInstruction::create($name),
145  array_filter(
146  $this->prototypeConfiguration['formEditor']['dynamicJavaScriptModules'] ?? [],
147  fn (string $name) => in_array($name, self::JS_MODULE_NAMES, true),
148  ARRAY_FILTER_USE_KEY
149  )
150  );
151  $pageRenderer = $this->pageRenderer;
152  $pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(
153  ‪JavaScriptModuleInstruction::create('@typo3/form/backend/helper.js', 'Helper')
154  ->invoke('dispatchFormEditor', $javaScriptModules, $formEditorAppInitialData)
155  );
156  array_map($pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(...), $javaScriptModules);
157  $pageRenderer->addInlineSettingArray(null, $addInlineSettings);
158  $pageRenderer->addInlineLanguageLabelFile('EXT:form/Resources/Private/Language/locallang_formEditor_failSafeErrorHandling_javascript.xlf');
159  $stylesheets = $this->‪resolveResourcePaths($this->prototypeConfiguration['formEditor']['stylesheets']);
160  foreach ($stylesheets as $stylesheet) {
161  $pageRenderer->addCssFile($stylesheet);
162  }
163 
164  $moduleTemplate->setModuleClass($this->request->getPluginName() . '_' . $this->request->getControllerName());
165  $moduleTemplate->setFlashMessageQueue($this->‪getFlashMessageQueue());
166  $moduleTemplate->setTitle(
167  $this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/locallang_module.xlf:mlang_tabs_tab'),
168  $formDefinition['label']
169  );
170  return $moduleTemplate->renderResponse('Backend/FormEditor/Index');
171  }
172 
177  public function ‪initializeSaveFormAction(): void
178  {
179  $this->defaultViewObjectName = JsonView::class;
180  }
181 
185  public function ‪saveFormAction(string $formPersistenceIdentifier, ‪FormDefinitionArray $formDefinition): ResponseInterface
186  {
187  $formDefinition = $formDefinition->getArrayCopy();
188 
189  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/form']['beforeFormSave'] ?? [] as $className) {
190  $hookObj = GeneralUtility::makeInstance($className);
191  if (method_exists($hookObj, 'beforeFormSave')) {
192  $formDefinition = $hookObj->beforeFormSave(
193  $formPersistenceIdentifier,
194  $formDefinition
195  );
196  }
197  }
198 
199  $response = [
200  'status' => 'success',
201  ];
202 
203  try {
204  if (!$this->formPersistenceManager->isAllowedPersistencePath($formPersistenceIdentifier)) {
205  throw new ‪PersistenceManagerException(sprintf('Save "%s" is not allowed', $formPersistenceIdentifier), 1614500663);
206  }
207  $this->formPersistenceManager->save($formPersistenceIdentifier, $formDefinition);
208  $configurationService = GeneralUtility::makeInstance(ConfigurationService::class);
209  $this->prototypeConfiguration = $configurationService->getPrototypeConfiguration($formDefinition['prototypeName']);
210  $formDefinition = $this->‪transformFormDefinitionForFormEditor($formDefinition);
211  $response['formDefinition'] = $formDefinition;
212  } catch (‪PersistenceManagerException $e) {
213  $response = [
214  'status' => 'error',
215  'message' => $e->getMessage(),
216  'code' => $e->getCode(),
217  ];
218  }
219 
220  $this->view->assign('response', $response);
221  // saveFormAction uses the extbase JsonView::class.
222  // That's why we have to set the view variables in this way.
223  $this->view->setVariablesToRender([
224  'response',
225  ]);
226 
227  return $this->‪jsonResponse();
228  }
229 
234  public function ‪renderFormPageAction(
235  ‪FormDefinitionArray $formDefinition,
236  int $pageIndex,
237  string $prototypeName = null
238  ): ResponseInterface {
239  $prototypeName = $prototypeName ?: $formDefinition['prototypeName'] ?? 'standard';
240  $formDefinition = $formDefinition->getArrayCopy();
241 
242  $formFactory = GeneralUtility::makeInstance(ArrayFormFactory::class);
243  $formDefinition = $formFactory->build($formDefinition, $prototypeName);
244  $formDefinition->setRenderingOption('previewMode', true);
245  $form = $formDefinition->bind($this->request);
246  $form->setCurrentSiteLanguage($this->‪buildFakeSiteLanguage(0, 0));
247  $form->overrideCurrentPage($pageIndex);
248 
249  return $this->‪htmlResponse($form->render());
250  }
251 
256  protected function ‪buildFakeSiteLanguage(int $pageId, int $languageId): ‪SiteLanguage
257  {
258  $fakeSiteConfiguration = [
259  'languages' => [
260  [
261  'languageId' => $languageId,
262  'title' => 'Dummy',
263  'navigationTitle' => '',
264  'flag' => '',
265  'locale' => '',
266  ],
267  ],
268  ];
269 
270  $currentSiteLanguage = GeneralUtility::makeInstance(Site::class, 'form-dummy', $pageId, $fakeSiteConfiguration)
271  ->getLanguageById($languageId);
272  return $currentSiteLanguage;
273  }
274 
279  protected function ‪getInsertRenderablesPanelConfiguration(array $formElementsDefinition): array
280  {
282  $formElementsByGroup = [];
283 
284  foreach ($formElementsDefinition as $formElementName => $formElementConfiguration) {
285  if (!isset($formElementConfiguration['group'])) {
286  continue;
287  }
288  if (!isset($formElementsByGroup[$formElementConfiguration['group']])) {
289  $formElementsByGroup[$formElementConfiguration['group']] = [];
290  }
291 
292  $formElementConfiguration = GeneralUtility::makeInstance(TranslationService::class)->translateValuesRecursive(
293  $formElementConfiguration,
294  $this->prototypeConfiguration['formEditor']['translationFiles'] ?? []
295  );
296 
297  $formElementsByGroup[$formElementConfiguration['group']][] = [
298  'key' => $formElementName,
299  'cssKey' => preg_replace('/[^a-z0-9]/', '-', strtolower($formElementName)),
300  'label' => $formElementConfiguration['label'],
301  'sorting' => $formElementConfiguration['groupSorting'],
302  'iconIdentifier' => $formElementConfiguration['iconIdentifier'],
303  ];
304  }
305 
306  $formGroups = [];
307  foreach ($this->prototypeConfiguration['formEditor']['formElementGroups'] ?? [] as $groupName => $groupConfiguration) {
308  if (!isset($formElementsByGroup[$groupName])) {
309  continue;
310  }
311 
312  usort($formElementsByGroup[$groupName], static function ($a, $b) {
313  return $a['sorting'] - $b['sorting'];
314  });
315  unset($formElementsByGroup[$groupName]['sorting']);
316 
317  $groupConfiguration = GeneralUtility::makeInstance(TranslationService::class)->translateValuesRecursive(
318  $groupConfiguration,
319  $this->prototypeConfiguration['formEditor']['translationFiles'] ?? []
320  );
321 
322  $formGroups[] = [
323  'key' => $groupName,
324  'elements' => $formElementsByGroup[$groupName],
325  'label' => $groupConfiguration['label'],
326  ];
327  }
328 
329  return $formGroups;
330  }
331 
335  protected function ‪getFormEditorDefinitions(): array
336  {
337  $formEditorDefinitions = [];
338  foreach ([$this->prototypeConfiguration, $this->prototypeConfiguration['formEditor']] as $configuration) {
339  foreach ($configuration as $firstLevelItemKey => $firstLevelItemValue) {
340  if (substr($firstLevelItemKey, -10) !== 'Definition') {
341  continue;
342  }
343  $reducedKey = substr($firstLevelItemKey, 0, -10);
344  foreach ($configuration[$firstLevelItemKey] as $formEditorDefinitionKey => $formEditorDefinitionValue) {
345  if (isset($formEditorDefinitionValue['formEditor'])) {
346  $formEditorDefinitionValue = array_intersect_key($formEditorDefinitionValue, array_flip(['formEditor']));
347  $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue['formEditor'];
348  } else {
349  $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue;
350  }
351  }
352  }
353  }
354  $formEditorDefinitions = ‪ArrayUtility::reIndexNumericArrayKeysRecursive($formEditorDefinitions);
355  $formEditorDefinitions = GeneralUtility::makeInstance(TranslationService::class)->translateValuesRecursive(
356  $formEditorDefinitions,
357  $this->prototypeConfiguration['formEditor']['translationFiles'] ?? []
358  );
359  return $formEditorDefinitions;
360  }
361 
366  {
367  $moduleTemplate = $this->moduleTemplateFactory->create(‪$request);
368 
369  $buttonBar = $moduleTemplate->‪getDocHeaderComponent()->getButtonBar();
370  $getVars = ‪$request->‪getArguments();
371 
372  if (isset($getVars['action']) && $getVars['action'] === 'index') {
373  $newPageButton = $buttonBar->makeInputButton()
374  ->setDataAttributes(['action' => 'formeditor-new-page', 'identifier' => 'headerNewPage'])
375  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.new_page_button'))
376  ->setName('formeditor-new-page')
377  ->setValue('new-page')
378  ->setClasses('t3-form-element-new-page-button hidden')
379  ->setIcon($this->iconFactory->getIcon('actions-page-new', IconSize::SMALL));
380 
381  ‪$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
382 
383  $closeButton = $buttonBar->makeLinkButton()
384  ->setDataAttributes(['identifier' => 'closeButton'])
385  ->setHref((string)‪$uriBuilder->buildUriFromRoute('web_FormFormbuilder'))
386  ->setClasses('t3-form-element-close-form-button hidden')
387  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.closeDoc'))
388  ->setShowLabelText(true)
389  ->setIcon($this->iconFactory->getIcon('actions-close', IconSize::SMALL));
390 
391  $saveButton = $buttonBar->makeInputButton()
392  ->setDataAttributes(['identifier' => 'saveButton'])
393  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.save_button'))
394  ->setName('formeditor-save-form')
395  ->setValue('save')
396  ->setClasses('t3-form-element-save-form-button hidden')
397  ->setIcon($this->iconFactory->getIcon('actions-document-save', IconSize::SMALL))
398  ->setShowLabelText(true);
399 
400  $formSettingsButton = $buttonBar->makeInputButton()
401  ->setDataAttributes(['identifier' => 'formSettingsButton'])
402  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.form_settings_button'))
403  ->setName('formeditor-form-settings')
404  ->setValue('settings')
405  ->setClasses('t3-form-element-form-settings-button hidden')
406  ->setIcon($this->iconFactory->getIcon('actions-system-extension-configure', IconSize::SMALL))
407  ->setShowLabelText(true);
408 
409  $undoButton = $buttonBar->makeInputButton()
410  ->setDataAttributes(['identifier' => 'undoButton'])
411  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.undo_button'))
412  ->setName('formeditor-undo-form')
413  ->setValue('undo')
414  ->setClasses('t3-form-element-undo-form-button hidden disabled')
415  ->setIcon($this->iconFactory->getIcon('actions-edit-undo', IconSize::SMALL));
416 
417  $redoButton = $buttonBar->makeInputButton()
418  ->setDataAttributes(['identifier' => 'redoButton'])
419  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.redo_button'))
420  ->setName('formeditor-redo-form')
421  ->setValue('redo')
422  ->setClasses('t3-form-element-redo-form-button hidden disabled')
423  ->setIcon($this->iconFactory->getIcon('actions-edit-redo', IconSize::SMALL));
424 
425  $buttonBar->addButton($newPageButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 1);
426  $buttonBar->addButton($closeButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 2);
427  $buttonBar->addButton($saveButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 3);
428  $buttonBar->addButton($formSettingsButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 4);
429  $buttonBar->addButton($undoButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 5);
430  $buttonBar->addButton($redoButton, ‪ButtonBar::BUTTON_POSITION_LEFT, 5);
431  }
432 
433  return $moduleTemplate;
434  }
435 
439  protected function ‪renderFormEditorTemplates(array $formEditorDefinitions): string
440  {
441  $fluidConfiguration = $this->prototypeConfiguration['formEditor']['formEditorFluidConfiguration'] ?? null;
442  $formEditorPartials = $this->prototypeConfiguration['formEditor']['formEditorPartials'] ?? null;
443 
444  if (!isset($fluidConfiguration['templatePathAndFilename'])) {
445  throw new ‪RenderingException(
446  'The option templatePathAndFilename must be set.',
447  1485636499
448  );
449  }
450  if (
451  !isset($fluidConfiguration['layoutRootPaths'])
452  || !is_array($fluidConfiguration['layoutRootPaths'])
453  ) {
454  throw new ‪RenderingException(
455  'The option layoutRootPaths must be set.',
456  1480294721
457  );
458  }
459  if (
460  !isset($fluidConfiguration['partialRootPaths'])
461  || !is_array($fluidConfiguration['partialRootPaths'])
462  ) {
463  throw new ‪RenderingException(
464  'The option partialRootPaths must be set.',
465  1480294722
466  );
467  }
468 
469  $insertRenderablesPanelConfiguration = $this->‪getInsertRenderablesPanelConfiguration($formEditorDefinitions['formElements']);
470 
471  ‪$view = GeneralUtility::makeInstance(TemplateView::class);
472  ‪$view->getRenderingContext()->setRequest($this->request);
473  ‪$view->getRenderingContext()->getTemplatePaths()->fillFromConfigurationArray($fluidConfiguration);
474  ‪$view->setTemplatePathAndFilename($fluidConfiguration['templatePathAndFilename']);
475  ‪$view->assignMultiple([
476  'insertRenderablesPanelConfiguration' => $insertRenderablesPanelConfiguration,
477  'formEditorPartials' => $formEditorPartials,
478  ]);
479 
480  return ‪$view->render();
481  }
482 
486  protected function ‪transformFormDefinitionForFormEditor(array $formDefinition): array
487  {
488  $multiValueFormElementProperties = [];
489  $multiValueFinisherProperties = [];
490 
491  foreach ($this->prototypeConfiguration['formElementsDefinition'] as $type => $configuration) {
492  if (!isset($configuration['formEditor']['editors'])) {
493  continue;
494  }
495  foreach ($configuration['formEditor']['editors'] as $editorConfiguration) {
496  if (($editorConfiguration['templateName'] ?? '') === 'Inspector-PropertyGridEditor') {
497  $multiValueFormElementProperties[$type][] = $editorConfiguration['propertyPath'];
498  }
499  }
500  }
501 
502  foreach ($this->prototypeConfiguration['formElementsDefinition']['Form']['formEditor']['propertyCollections']['finishers'] ?? [] as $configuration) {
503  if (!isset($configuration['editors'])) {
504  continue;
505  }
506 
507  foreach ($configuration['editors'] as $editorConfiguration) {
508  if (($editorConfiguration['templateName'] ?? '') === 'Inspector-PropertyGridEditor') {
509  $multiValueFinisherProperties[$configuration['identifier']][] = $editorConfiguration['propertyPath'];
510  }
511  }
512  }
513 
514  $formDefinition = $this->‪filterEmptyArrays($formDefinition);
515  $formDefinition = $this->‪migrateEmailFinisherRecipients($formDefinition);
516 
517  // @todo: replace with rte parsing
518  $formDefinition = ArrayUtility::stripTagsFromValuesRecursive($formDefinition);
519  $formDefinition = $this->‪transformMultiValuePropertiesForFormEditor(
520  $formDefinition,
521  'type',
522  $multiValueFormElementProperties
523  );
524  $formDefinition = $this->‪transformMultiValuePropertiesForFormEditor(
525  $formDefinition,
526  'identifier',
527  $multiValueFinisherProperties
528  );
529 
530  $formDefinition = $this->formDefinitionConversionService->addHmacData($formDefinition);
531  $formDefinition = $this->formDefinitionConversionService->migrateFinisherConfiguration($formDefinition);
532 
533  return $formDefinition;
534  }
535 
567  array $formDefinition,
568  string $identifierProperty,
569  array $multiValueProperties
570  ): array {
571  ‪$output = $formDefinition;
572  foreach ($formDefinition as $key => $value) {
573  ‪$identifier = $value[$identifierProperty] ?? null;
574 
575  if (array_key_exists(‪$identifier, $multiValueProperties)) {
576  $multiValuePropertiesForIdentifier = $multiValueProperties[‪$identifier];
577 
578  foreach ($multiValuePropertiesForIdentifier as $multiValueProperty) {
579  if (!‪ArrayUtility::isValidPath($value, $multiValueProperty, '.')) {
580  continue;
581  }
582 
583  $multiValuePropertyData = ‪ArrayUtility::getValueByPath($value, $multiValueProperty, '.');
584 
585  if (!is_array($multiValuePropertyData)) {
586  continue;
587  }
588 
589  $newMultiValuePropertyData = [];
590 
591  foreach ($multiValuePropertyData as $k => $v) {
592  $newMultiValuePropertyData[] = [
593  '_label' => $v,
594  '_value' => $k,
595  ];
596  }
597 
598  $value = ‪ArrayUtility::setValueByPath($value, $multiValueProperty, $newMultiValuePropertyData, '.');
599  }
600  }
601 
602  ‪$output[$key] = $value;
603 
604  if (is_array($value)) {
606  $value,
607  $identifierProperty,
608  $multiValueProperties
609  );
610  }
611  }
612 
613  return ‪$output;
614  }
615 
619  protected function ‪filterEmptyArrays(array $array): array
620  {
621  foreach ($array as $key => $value) {
622  if (!is_array($value)) {
623  continue;
624  }
625  if (empty($value)) {
626  unset($array[$key]);
627  continue;
628  }
629  $array[$key] = $this->‪filterEmptyArrays($value);
630  if (empty($array[$key])) {
631  unset($array[$key]);
632  }
633  }
634 
635  return $array;
636  }
637 
641  protected function ‪migrateEmailFinisherRecipients(array $formDefinition): array
642  {
643  foreach ($formDefinition['finishers'] ?? [] as $i => $finisherConfiguration) {
644  if (!in_array($finisherConfiguration['identifier'], ['EmailToSender', 'EmailToReceiver'], true)) {
645  continue;
646  }
647 
648  $recipientAddress = $finisherConfiguration['options']['recipientAddress'] ?? '';
649  $recipientName = $finisherConfiguration['options']['recipientName'] ?? '';
650  $carbonCopyAddress = $finisherConfiguration['options']['carbonCopyAddress'] ?? '';
651  $blindCarbonCopyAddress = $finisherConfiguration['options']['blindCarbonCopyAddress'] ?? '';
652  $replyToAddress = $finisherConfiguration['options']['replyToAddress'] ?? '';
653 
654  if (!empty($recipientAddress)) {
655  $finisherConfiguration['options']['recipients'][$recipientAddress] = $recipientName;
656  }
657 
658  if (!empty($carbonCopyAddress)) {
659  $finisherConfiguration['options']['carbonCopyRecipients'][$carbonCopyAddress] = '';
660  }
661 
662  if (!empty($blindCarbonCopyAddress)) {
663  $finisherConfiguration['options']['blindCarbonCopyRecipients'][$blindCarbonCopyAddress] = '';
664  }
665 
666  if (!empty($replyToAddress)) {
667  $finisherConfiguration['options']['replyToRecipients'][$replyToAddress] = '';
668  }
669 
670  unset(
671  $finisherConfiguration['options']['recipientAddress'],
672  $finisherConfiguration['options']['recipientName'],
673  $finisherConfiguration['options']['carbonCopyAddress'],
674  $finisherConfiguration['options']['blindCarbonCopyAddress'],
675  $finisherConfiguration['options']['replyToAddress']
676  );
677  $formDefinition['finishers'][$i] = $finisherConfiguration;
678  }
679 
680  return $formDefinition;
681  }
682 
684  {
685  return ‪$GLOBALS['BE_USER'];
686  }
687 
689  {
690  return ‪$GLOBALS['LANG'];
691  }
692 }
‪TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory
Definition: ArrayFormFactory.php:39
‪TYPO3\CMS\Core\Utility\PathUtility\isExtensionPath
‪static isExtensionPath(string $path)
Definition: PathUtility.php:117
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:27
‪TYPO3\CMS\Backend\Template\Components\ButtonBar\BUTTON_POSITION_LEFT
‪const BUTTON_POSITION_LEFT
Definition: ButtonBar.php:37
‪TYPO3\CMS\Backend\Template\Components\ButtonBar
Definition: ButtonBar.php:33
‪TYPO3\CMS\Form\Controller\FormEditorController
Definition: FormEditorController.php:55
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$request
‪RequestInterface $request
Definition: ActionController.php:122
‪TYPO3\CMS\Form\Service\TranslationService
Definition: TranslationService.php:45
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException
Definition: PersistenceManagerException.php:28
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$view
‪ViewInterface $view
Definition: ActionController.php:89
‪TYPO3\CMS\Form\Domain\Configuration\FormDefinitionConversionService
Definition: FormDefinitionConversionService.php:35
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪TYPO3\CMS\Form\Controller
Definition: AbstractBackendController.php:18
‪TYPO3\CMS\Form\Controller\FormEditorController\transformMultiValuePropertiesForFormEditor
‪transformMultiValuePropertiesForFormEditor(array $formDefinition, string $identifierProperty, array $multiValueProperties)
Definition: FormEditorController.php:566
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Core\Utility\ArrayUtility\isValidPath
‪static bool isValidPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:141
‪TYPO3\CMS\Form\Controller\AbstractBackendController\resolveResourcePaths
‪resolveResourcePaths(array $resourcePaths)
Definition: AbstractBackendController.php:67
‪TYPO3\CMS\Fluid\View\TemplateView
Definition: TemplateView.php:22
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static getValueByPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:176
‪TYPO3\CMS\Form\Controller\FormEditorController\getBackendUser
‪getBackendUser()
Definition: FormEditorController.php:683
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:27
‪TYPO3\CMS\Form\Controller\FormEditorController\$prototypeConfiguration
‪array $prototypeConfiguration
Definition: FormEditorController.php:58
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:46
‪TYPO3\CMS\Form\Controller\FormEditorController\getInsertRenderablesPanelConfiguration
‪getInsertRenderablesPanelConfiguration(array $formElementsDefinition)
Definition: FormEditorController.php:279
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\htmlResponse
‪htmlResponse(string $html=null)
Definition: ActionController.php:839
‪TYPO3\CMS\Form\Exception
Definition: Exception.php:26
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\jsonResponse
‪jsonResponse(string $json=null)
Definition: ActionController.php:852
‪TYPO3\CMS\Form\Controller\FormEditorController\indexAction
‪indexAction(string $formPersistenceIdentifier, string $prototypeName=null)
Definition: FormEditorController.php:73
‪TYPO3\CMS\Form\Controller\FormEditorController\renderFormEditorTemplates
‪renderFormEditorTemplates(array $formEditorDefinitions)
Definition: FormEditorController.php:439
‪TYPO3\CMS\Form\Controller\FormEditorController\getFormEditorDefinitions
‪getFormEditorDefinitions()
Definition: FormEditorController.php:335
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Form\Controller\FormEditorController\__construct
‪__construct(protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly PageRenderer $pageRenderer, protected readonly IconFactory $iconFactory, protected readonly FormDefinitionConversionService $formDefinitionConversionService,)
Definition: FormEditorController.php:60
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\$uriBuilder
‪TYPO3 CMS Extbase Mvc Web Routing UriBuilder $uriBuilder
Definition: ActionController.php:126
‪TYPO3\CMS\Form\Controller\FormEditorController\renderFormPageAction
‪renderFormPageAction(FormDefinitionArray $formDefinition, int $pageIndex, string $prototypeName=null)
Definition: FormEditorController.php:234
‪TYPO3\CMS\Form\Type\FormDefinitionArray
Definition: FormDefinitionArray.php:25
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:64
‪TYPO3\CMS\Form\Controller\FormEditorController\getLanguageService
‪getLanguageService()
Definition: FormEditorController.php:688
‪TYPO3\CMS\Form\Controller\FormEditorController\buildFakeSiteLanguage
‪buildFakeSiteLanguage(int $pageId, int $languageId)
Definition: FormEditorController.php:256
‪TYPO3\CMS\Form\Domain\Configuration\ConfigurationService
Definition: ConfigurationService.php:50
‪$output
‪$output
Definition: annotationChecker.php:119
‪TYPO3\CMS\Extbase\Mvc\RequestInterface
Definition: RequestInterface.php:24
‪TYPO3\CMS\Backend\Template\ModuleTemplate\getDocHeaderComponent
‪getDocHeaderComponent()
Definition: ModuleTemplate.php:181
‪TYPO3\CMS\Form\Controller\FormEditorController\migrateEmailFinisherRecipients
‪migrateEmailFinisherRecipients(array $formDefinition)
Definition: FormEditorController.php:641
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Utility\ArrayUtility\reIndexNumericArrayKeysRecursive
‪static reIndexNumericArrayKeysRecursive(array $array)
Definition: ArrayUtility.php:204
‪TYPO3\CMS\Form\Controller\FormEditorController\saveFormAction
‪saveFormAction(string $formPersistenceIdentifier, FormDefinitionArray $formDefinition)
Definition: FormEditorController.php:185
‪TYPO3\CMS\Extbase\Mvc\Controller\ActionController\getFlashMessageQueue
‪getFlashMessageQueue(string $identifier=null)
Definition: ActionController.php:693
‪TYPO3\CMS\Core\Utility\ArrayUtility\setValueByPath
‪static array setValueByPath(array $array, string|array|\ArrayAccess $path, mixed $value, string $delimiter='/')
Definition: ArrayUtility.php:261
‪TYPO3\CMS\Form\Domain\Exception\RenderingException
Definition: RenderingException.php:30
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Form\Controller\FormEditorController\initializeSaveFormAction
‪initializeSaveFormAction()
Definition: FormEditorController.php:177
‪TYPO3\CMS\Form\Controller\AbstractBackendController
Definition: AbstractBackendController.php:33
‪TYPO3\CMS\Form\Controller\FormEditorController\JS_MODULE_NAMES
‪const JS_MODULE_NAMES
Definition: FormEditorController.php:56
‪TYPO3\CMS\Extbase\Mvc\View\JsonView
Definition: JsonView.php:29
‪TYPO3\CMS\Extbase\Mvc\RequestInterface\getArguments
‪getArguments()
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Form\Controller\FormEditorController\transformFormDefinitionForFormEditor
‪transformFormDefinitionForFormEditor(array $formDefinition)
Definition: FormEditorController.php:486
‪TYPO3\CMS\Form\Controller\FormEditorController\filterEmptyArrays
‪filterEmptyArrays(array $array)
Definition: FormEditorController.php:619
‪TYPO3\CMS\Form\Controller\FormEditorController\initializeModuleTemplate
‪initializeModuleTemplate(RequestInterface $request)
Definition: FormEditorController.php:365