commit aad9daaefd25a66c98ffec20518e7084c39872a2 Author: Sven Wappler Date: Mon Aug 10 22:31:24 2026 +0200 TYPO3 v15 dev-main snapshot () diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57872d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/Classes/Command/CleanupFormUploadsCommand.php b/Classes/Command/CleanupFormUploadsCommand.php new file mode 100644 index 0000000..63be9d9 --- /dev/null +++ b/Classes/Command/CleanupFormUploadsCommand.php @@ -0,0 +1,197 @@ +` sub-folders. + * Over time these folders accumulate — both from completed and incomplete form submissions. + * Since files are not moved upon submission, there is no way to distinguish between + * the two. This command removes form upload folders older than a configurable retention period. + * + * Usage examples: + * # Dry-run: list form upload folders older than 2 weeks (default) + * bin/typo3 form:cleanup:uploads 1:/user_upload/ --dry-run + * + * # Delete folders older than 48 hours in specific upload folders + * bin/typo3 form:cleanup:uploads 1:/user_upload/ 2:/custom_uploads/ --retention-period=48 + * + * # Force deletion without confirmation (e.g. for scheduler) + * bin/typo3 form:cleanup:uploads 1:/user_upload/ --force + */ +#[AsCommand('form:cleanup:uploads', 'Remove old form file upload folders based on retention period.')] +class CleanupFormUploadsCommand extends Command +{ + private const int DEFAULT_RETENTION_PERIOD_HOURS = 336; + + public function __construct( + private readonly CleanupFormUploadsService $cleanupService, + ) { + parent::__construct(); + } + + protected function configure(): void + { + $this + ->setHelp( + 'Removes old form upload folders (form_) that were created by file uploads ' + . 'in ext:form.' . LF . LF + . 'Since uploaded files are not moved when a form is submitted, the command cannot ' . LF + . 'distinguish between folders from completed and abandoned submissions. It uses ' . LF + . 'the folder modification time and a configurable retention period to decide ' . LF + . 'which folders to remove.' . LF . LF + . 'You must specify at least one upload folder to scan. Each form element can configure ' . LF + . 'a different saveToFileMount; pass all relevant folders as arguments.' . LF . LF + . 'Use --verbose for detailed output about each folder found.' + ) + ->addArgument( + 'upload-folder', + InputArgument::REQUIRED | InputArgument::IS_ARRAY, + 'Combined folder identifier(s) to scan (e.g. "1:/user_upload/").', + ) + ->addOption( + 'retention-period', + 'r', + InputOption::VALUE_REQUIRED, + 'Minimum age in hours before a form upload folder is considered for removal.', + (string)self::DEFAULT_RETENTION_PERIOD_HOURS, + ) + ->addOption( + 'dry-run', + null, + InputOption::VALUE_NONE, + 'Only list expired folders without deleting them.', + ) + ->addOption( + 'force', + 'f', + InputOption::VALUE_NONE, + 'Skip the confirmation question. Automatically set when using --no-interaction.', + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + + $retentionHours = (int)$input->getOption('retention-period'); + if ($retentionHours < 1) { + $io->error('The retention period must be at least 1 hour.'); + return Command::FAILURE; + } + + $maximumAgeSeconds = $retentionHours * 3600; + /** @var list $uploadFolders */ + $uploadFolders = $input->getArgument('upload-folder'); + $isDryRun = (bool)$input->getOption('dry-run'); + + $io->section(sprintf( + 'Scanning %s for form upload folders older than %d hour(s)', + 'folders: ' . implode(', ', $uploadFolders), + $retentionHours, + )); + + $expiredFolders = $this->cleanupService->getExpiredFolders($maximumAgeSeconds, $uploadFolders); + + if ($expiredFolders === []) { + $io->success('No expired form upload folders found. Nothing to do.'); + return Command::SUCCESS; + } + + if ($output->isVerbose()) { + foreach ($expiredFolders as $folder) { + $age = time() - $folder->getModificationTime(); + $ageHours = round($age / 3600, 1); + $fileCount = $folder->getFileCount(); + $io->writeln(sprintf( + ' [FOLDER] %s (age: %s hours, files: %d)', + $folder->getCombinedIdentifier(), + $ageHours, + $fileCount, + )); + } + } + + $totalFiles = 0; + foreach ($expiredFolders as $folder) { + $totalFiles += $folder->getFileCount(); + } + + $io->writeln(sprintf( + 'Found %d folder(s) containing %d file(s).', + count($expiredFolders), + $totalFiles, + )); + + if ($isDryRun) { + $io->note('Dry-run mode: no folders were deleted.'); + return Command::SUCCESS; + } + + // Do not ask for confirmation when running the command in EXT:scheduler + if (!$input->isInteractive()) { + $input->setOption('force', true); + } + + if (!$input->getOption('force')) { + /** @var QuestionHelper $questionHelper */ + $questionHelper = $this->getHelper('question'); + $question = new ConfirmationQuestion( + sprintf( + 'Are you sure you want to delete %d folder(s) with %d file(s)? [default: no] ', + count($expiredFolders), + $totalFiles, + ), + false, + ); + if (!$questionHelper->ask($input, $output, $question)) { + $io->note('Aborted by user.'); + return Command::SUCCESS; + } + } + + $result = $this->cleanupService->deleteFolders($expiredFolders); + + if ($result['deleted'] > 0) { + $io->success(sprintf('Successfully deleted %d form upload folder(s).', $result['deleted'])); + } + + if ($result['failed'] > 0) { + $io->warning(sprintf('Failed to delete %d folder(s).', $result['failed'])); + if ($output->isVerbose()) { + foreach ($result['errors'] as $error) { + $io->writeln(sprintf(' [ERROR] %s: %s', $error['folder'], $error['message'])); + } + } + } + + return $result['failed'] > 0 ? Command::FAILURE : Command::SUCCESS; + } +} diff --git a/Classes/Command/TransferFormDefinitionCommand.php b/Classes/Command/TransferFormDefinitionCommand.php new file mode 100644 index 0000000..466b0dc --- /dev/null +++ b/Classes/Command/TransferFormDefinitionCommand.php @@ -0,0 +1,285 @@ +setHelp( + 'Transfers form definitions from one storage backend to another.' . LF . LF + . 'Available storage types depend on the installed adapters. Core provides:' . LF + . ' - database: Database storage (default target)' . LF + . ' - extension: Extension paths (EXT:...)' . LF + . ' - filemount: File mount storage (deprecated since v14.2)' . LF . LF + . 'Target location (--target-location / -l) per storage type:' . LF + . ' - database: Always "0" (fixed; forms are stored at the root level).' . LF + . ' - extension: An EXT: path configured in "persistenceManager.allowedExtensionPaths",' . LF + . ' with "persistenceManager.allowSaveToExtensionPaths: true" set.' . LF + . ' e.g. --target-location="EXT:my_extension/Resources/Private/Forms/"' . LF . LF + . 'Use --dry-run to preview which forms would be transferred.' . LF + . 'Use --move to delete the source form after successful transfer.' . LF . LF + . 'After a successful transfer, content element references in "tt_content" are automatically' . LF + . 'updated to point to the new storage location. No other tables are updated.' + ) + ->addOption( + 'source', + null, + InputOption::VALUE_REQUIRED, + 'Source storage type identifier (e.g., "extension", "filemount", "database").', + ) + ->addOption( + 'target', + null, + InputOption::VALUE_REQUIRED, + 'Target storage type identifier (e.g., "database", "extension").', + ) + ->addOption( + 'target-location', + 'l', + InputOption::VALUE_REQUIRED, + 'Target storage location. For "database": always "0". For "extension": EXT: path from allowedExtensionPaths.', + '0', + ) + ->addOption( + 'form-identifier', + 'f', + InputOption::VALUE_REQUIRED, + 'Transfer only the form with this identifier. If omitted, all forms from the source are transferred.', + ) + ->addOption( + 'move', + 'm', + InputOption::VALUE_NONE, + 'Delete the source form after successful transfer (move operation).', + ) + ->addOption( + 'dry-run', + null, + InputOption::VALUE_NONE, + 'Only list forms that would be transferred without making changes.', + ); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + Bootstrap::initializeBackendAuthentication(); + + // @todo: ConfigurationManager triggered by PersistenceConfigurationService needs a Request + $request = (new ServerRequest('https://localhost/', 'GET')); + $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE) + ->withAttribute('normalizedParams', NormalizedParams::createFromRequest($request)); + $GLOBALS['TYPO3_REQUEST'] = $request; + + $io = new SymfonyStyle($input, $output); + $sourceType = $input->getOption('source'); + $targetType = $input->getOption('target'); + $targetLocation = $input->getOption('target-location'); + $formIdentifier = $input->getOption('form-identifier'); + $isMove = (bool)$input->getOption('move'); + $isDryRun = (bool)$input->getOption('dry-run'); + + if ($sourceType === null || $targetType === null) { + $io->error('Both --source and --target options are required.'); + $io->note(sprintf( + 'Available storage types: %s', + implode(', ', $this->formTransferService->getAvailableStorageTypes()), + )); + return Command::FAILURE; + } + + if (!$this->formTransferService->hasStorageType($sourceType)) { + $io->error(sprintf( + 'Unknown source storage type "%s". Available types: %s', + $sourceType, + implode(', ', $this->formTransferService->getAvailableStorageTypes()), + )); + return Command::FAILURE; + } + + if (!$this->formTransferService->hasStorageType($targetType)) { + $io->error(sprintf( + 'Unknown target storage type "%s". Available types: %s', + $targetType, + implode(', ', $this->formTransferService->getAvailableStorageTypes()), + )); + return Command::FAILURE; + } + + if ($sourceType === $targetType && $formIdentifier === null) { + $io->error('Source and target storage types are identical. Use --form-identifier to transfer a specific form, or choose different storage types.'); + return Command::FAILURE; + } + + $targetAdapter = $this->formTransferService->getAdapter($targetType); + if (!$targetAdapter->isAllowedStorageLocation($targetLocation)) { + $hint = match ($targetType) { + 'database' => 'For database storage the only valid location is "0" (default). The option can be omitted.', + 'extension' => 'For extension storage, provide an EXT: path that is registered in "persistenceManager.allowedExtensionPaths"' . LF + . 'and ensure "persistenceManager.allowSaveToExtensionPaths: true" is set in your form YAML setup.' . LF + . 'Example: --target-location="EXT:my_extension/Resources/Private/Forms/"', + default => 'Check the storage adapter documentation for valid location formats.', + }; + $io->error(sprintf( + 'The target location "%s" is not valid for the "%s" storage adapter.' . LF . '%s', + $targetLocation, + $targetType, + $hint, + )); + return Command::FAILURE; + } + + $sourceForms = $this->formTransferService->listSourceForms($sourceType, $formIdentifier); + + if ($sourceForms === []) { + $message = $formIdentifier !== null + ? sprintf('No form with identifier "%s" found in "%s" storage.', $formIdentifier, $sourceType) + : sprintf('No forms found in "%s" storage.', $sourceType); + $io->warning($message); + return Command::SUCCESS; + } + + $operation = $isMove ? 'move' : 'transfer'; + $io->section(sprintf( + 'Found %d form(s) to %s from "%s" to "%s"', + count($sourceForms), + $operation, + $sourceType, + $targetType, + )); + + if ($isDryRun) { + $rows = []; + foreach ($sourceForms as $form) { + $rows[] = [ + $form->identifier, + $form->name, + $form->persistenceIdentifier ?? '-', + 'would ' . $operation . '', + ]; + } + $io->table(['Identifier', 'Name', 'Source', 'Status'], $rows); + $io->note('Dry-run mode: no forms were transferred.'); + return Command::SUCCESS; + } + + $transferred = 0; + $failed = 0; + $results = []; + $migrationMap = []; + + foreach ($sourceForms as $form) { + try { + $result = $this->formTransferService->transferForm( + $form, + $sourceType, + $targetType, + $targetLocation, + $isMove, + ); + + $status = 'success'; + if ($isMove && $result->sourceDeleted) { + $status = 'moved'; + } elseif ($isMove && $result->deletionError !== null) { + $status = 'transferred, source deletion failed: ' . $result->deletionError . ''; + } + + $results[] = [ + $result->formIdentifier, + $result->formName, + $result->sourceIdentifier, + $result->targetIdentifier, + $status, + ]; + $migrationMap[$result->sourceIdentifier] = $result->targetIdentifier; + $transferred++; + } catch (\Exception $e) { + $results[] = [ + $form->identifier, + $form->name, + $form->persistenceIdentifier ?? '-', + '-', + '' . $e->getMessage() . '', + ]; + $failed++; + if ($output->isVerbose()) { + $io->error(sprintf('Failed to transfer "%s": %s', $form->identifier, $e->getMessage())); + } + } + } + + $io->table(['Identifier', 'Name', 'Source', 'Target', 'Status'], $results); + + if ($migrationMap !== []) { + $referencesUpdated = $this->formTransferService->updateContentElementReferences($migrationMap); + if ($referencesUpdated > 0) { + $io->note(sprintf('Updated %d content element reference(s).', $referencesUpdated)); + } + } + + if ($transferred > 0) { + $verb = $isMove ? 'moved' : 'transferred'; + $io->success(sprintf('Successfully %s %d form(s) from "%s" to "%s".', $verb, $transferred, $sourceType, $targetType)); + } + if ($failed > 0) { + $io->warning(sprintf('Failed to transfer %d form(s).', $failed)); + } + + return $failed > 0 ? Command::FAILURE : Command::SUCCESS; + } +} diff --git a/Classes/ConfigurationModuleProvider/FormYamlProvider.php b/Classes/ConfigurationModuleProvider/FormYamlProvider.php new file mode 100644 index 0000000..b573b93 --- /dev/null +++ b/Classes/ConfigurationModuleProvider/FormYamlProvider.php @@ -0,0 +1,69 @@ +identifier = $attributes['identifier']; + return $this; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function getLabel(): string + { + return $this->getLanguageService()->sL( + 'LLL:EXT:form/Resources/Private/Language/locallang.xlf:form.configuration.module.provider' + ); + } + + public function getConfiguration(): array + { + // Another hidden dependency to $GLOBALS['TYPO3_REQUEST'] made explicit here. + $request = $GLOBALS['TYPO3_REQUEST']; + $extbaseConfigurationManager = $this->extbaseConfigurationManager; + $extbaseConfigurationManager->setRequest($request); + $typoScriptSettings = $extbaseConfigurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $configuration = $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, false); + ArrayUtility::naturalKeySortRecursive($configuration); + return $configuration; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Controller/FormEditorController.php b/Classes/Controller/FormEditorController.php new file mode 100644 index 0000000..cd6de1e --- /dev/null +++ b/Classes/Controller/FormEditorController.php @@ -0,0 +1,666 @@ +coreUriBuilder->buildUriFromRoute('form_manager')); + } + $formSettings = $this->getFormSettings(); + if (!$this->formPersistenceManager->isAllowedPersistenceIdentifier($formPersistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('Read "%s" is not allowed', $formPersistenceIdentifier), 1614500662); + } + if (PathUtility::isExtensionPath($formPersistenceIdentifier) + && !PersistenceManagerConfiguration::fromArray($formSettings['persistenceManager'] ?? [])->allowSaveToExtensionPaths + ) { + throw new PersistenceManagerException('Edit an extension formDefinition is not allowed.', 1478265661); + } + $formDefinition = $this->formPersistenceManager->load($formPersistenceIdentifier); + if ($prototypeName === null) { + $prototypeName = $formDefinition['prototypeName'] ?? 'standard'; + } else { + // Loading a form definition with another prototype is currently not implemented but is planned in the future. + // This safety check is a preventive measure. + $selectablePrototypeNames = $this->configurationService->getSelectablePrototypeNamesDefinedInFormEditorSetup(); + if (!in_array($prototypeName, $selectablePrototypeNames, true)) { + throw new Exception(sprintf('The prototype name "%s" is not configured within "formManager.selectablePrototypesConfiguration" ', $prototypeName), 1528625039); + } + } + $formDefinition['prototypeName'] = $prototypeName; + $prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($prototypeName); + $formDefinition = $this->transformFormDefinitionForFormEditor($prototypeConfiguration, $formDefinition, $formPersistenceIdentifier); + $formEditorDefinitions = $this->getFormEditorDefinitions($prototypeConfiguration); + $additionalViewModelJavaScriptModules = array_map( + static fn(string $name) => JavaScriptModuleInstruction::create($name), + $prototypeConfiguration['formEditor']['dynamicJavaScriptModules']['additionalViewModelModules'] ?? [] + ); + array_map($this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(...), $additionalViewModelJavaScriptModules); + $formEditorAppInitialData = [ + 'formEditorDefinitions' => $formEditorDefinitions, + 'formDefinition' => $formDefinition, + 'formPersistenceIdentifier' => $formPersistenceIdentifier, + 'prototypeName' => $prototypeName, + 'endpoints' => [ + 'formPageRenderer' => $this->uriBuilder->uriFor('renderFormPage'), + 'saveForm' => $this->uriBuilder->uriFor('saveForm'), + ], + 'additionalViewModelModules' => $additionalViewModelJavaScriptModules, + 'maximumUndoSteps' => $prototypeConfiguration['formEditor']['maximumUndoSteps'], + ]; + $moduleTemplate = $this->initializeModuleTemplate($this->request, $returnUrl); + $moduleTemplate->assign('formEditorTemplates', $this->renderFormEditorTemplates($prototypeConfiguration, $formEditorDefinitions)); + $moduleTemplate->getDocHeaderComponent()->addBreadcrumbSuffixNode(new BreadcrumbNode( + identifier: $formPersistenceIdentifier, + label: $formDefinition['label'], + icon: 'content-form', + )); + $addInlineSettings = [ + 'FormEditor' => [ + 'typo3WinBrowserUrl' => (string)$this->coreUriBuilder->buildUriFromRoute('wizard_element_browser'), + 'dateEditor' => [ + 'absolutePattern' => DateRangeValidatorPatterns::RFC3339_FULL_DATE, + ], + ], + ]; + $addInlineSettings = array_replace_recursive( + $addInlineSettings, + $prototypeConfiguration['formEditor']['addInlineSettings'] + ); + if (json_encode($formEditorAppInitialData) === false) { + throw new Exception('The form editor app data could not be encoded', 1628677079); + } + $javaScriptModules = array_map( + static fn(string $name) => JavaScriptModuleInstruction::create($name), + array_filter( + $prototypeConfiguration['formEditor']['dynamicJavaScriptModules'] ?? [], + fn(string $name) => in_array($name, self::JS_MODULE_NAMES, true), + ARRAY_FILTER_USE_KEY + ) + ); + $pageRenderer = $this->pageRenderer; + $pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction( + JavaScriptModuleInstruction::create('@typo3/form/backend/helper.js', 'Helper') + ->invoke('dispatchFormEditor', $javaScriptModules, $formEditorAppInitialData) + ); + array_map($pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(...), $javaScriptModules); + $pageRenderer->addInlineSettingArray('', $addInlineSettings); + $stylesheets = $prototypeConfiguration['formEditor']['stylesheets']; + foreach ($stylesheets as $stylesheet) { + $pageRenderer->addCssFile($stylesheet); + } + $moduleTemplate->setModuleClass($this->request->getPluginName() . '_' . $this->request->getControllerName()); + $moduleTemplate->setFlashMessageQueue($this->getFlashMessageQueue()); + $moduleTemplate->setTitle( + $this->getLanguageService()->translate('title', 'form.module'), + $formDefinition['label'] + ); + return $moduleTemplate->renderResponse('Backend/FormEditor/Index'); + } + + /** + * Initialize the save action. + * This action uses the Fluid JsonView::class as view. + */ + protected function initializeSaveFormAction(): void + { + $this->assertAllowedHttpMethod($this->request, 'POST'); + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Save a formDefinition which was build by the form editor. + */ + protected function saveFormAction(string $formPersistenceIdentifier, FormDefinitionArray $formDefinition): ResponseInterface + { + $formDefinition = $formDefinition->getArrayCopy(); + $event = $this->eventDispatcher->dispatch( + new BeforeFormIsSavedEvent($formPersistenceIdentifier, $formDefinition, $this->request), + ); + $formPersistenceIdentifier = $event->formPersistenceIdentifier; + $formDefinition = $event->form; + $response = [ + 'status' => 'success', + ]; + try { + if (!$this->formPersistenceManager->isAllowedPersistenceIdentifier($formPersistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('Save "%s" is not allowed', $formPersistenceIdentifier), 1614500663); + } + $this->formPersistenceManager->save($formPersistenceIdentifier, $formDefinition, []); + $this->flushPageCache($formPersistenceIdentifier); + $prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($formDefinition['prototypeName']); + $formDefinition = $this->transformFormDefinitionForFormEditor($prototypeConfiguration, $formDefinition, $formPersistenceIdentifier); + $response['formDefinition'] = $formDefinition; + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + // saveFormAction uses the extbase JsonView::class. + // That's why we have to set the view variables in this way. + /** @var JsonView $view */ + $view = $this->view; + $view->assign('response', $response); + $view->setVariablesToRender([ + 'response', + ]); + return $this->jsonResponse(); + } + + /** + * Render a page from the formDefinition which was build by the form editor. + * Use the frontend rendering and set the form framework to preview mode. + */ + protected function renderFormPageAction( + FormDefinitionArray $formDefinition, + int $pageIndex, + ?string $prototypeName = null, + ?string $formPersistenceIdentifier = null + ): ResponseInterface { + $prototypeName = $prototypeName ?: $formDefinition['prototypeName'] ?? 'standard'; + $formDefinition = $formDefinition->getArrayCopy(); + $formDefinition['renderingOptions']['previewMode'] = true; + $formDefinition = $this->arrayFormFactory->build($formDefinition, $prototypeName, $this->request); + + if ($formPersistenceIdentifier !== null) { + $formDefinition->setRenderingOption('formPersistenceIdentifier', $formPersistenceIdentifier); + } + + $form = $formDefinition->bind($this->request); + $form->setCurrentSiteLanguage($this->buildFakeSiteLanguage(0, 0)); + $form->overrideCurrentPage($pageIndex); + return $this->htmlResponse($form->render()); + } + + protected function getFormSettings(): array + { + $typoScriptSettings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $formSettings = $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, false); + if (!isset($formSettings['formManager'])) { + // Config sub array formManager is crucial and should always exist. If it does + // not, this indicates an issue in config loading logic. Except in this case. + throw new \LogicException('Configuration could not be loaded', 1681549038); + } + return $formSettings; + } + + /** + * Build a SiteLanguage object to render the form preview with a + * specific language. + */ + protected function buildFakeSiteLanguage(int $pageId, int $languageId): SiteLanguage + { + $fakeSiteConfiguration = [ + 'languages' => [ + [ + 'languageId' => $languageId, + 'title' => 'Dummy', + 'navigationTitle' => '', + 'flag' => '', + 'locale' => '', + ], + ], + ]; + return GeneralUtility::makeInstance(Site::class, 'form-dummy', $pageId, $fakeSiteConfiguration)->getLanguageById($languageId); + } + + /** + * Prepare the formElements.*.formEditor section from the YAML settings. + * Sort all formElements into groups and add additional data. + */ + protected function getInsertRenderablesPanelConfiguration(array $prototypeConfiguration, array $formElementsDefinition, bool $isInsertPages = false): array + { + /** @var array>> $formElementsByGroup */ + $formElementsByGroup = []; + foreach ($formElementsDefinition as $formElementName => $formElementConfiguration) { + if (!isset($formElementConfiguration['group']) || ($isInsertPages && $formElementConfiguration['group'] !== 'page') || (!$isInsertPages && $formElementConfiguration['group'] === 'page')) { + continue; + } + if (!isset($formElementsByGroup[$formElementConfiguration['group']])) { + $formElementsByGroup[$formElementConfiguration['group']] = []; + } + $formElementConfiguration = $this->translationService->translateValuesRecursive( + $formElementConfiguration, + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + $formElementsByGroup[$formElementConfiguration['group']][] = [ + 'identifier' => $formElementName, + 'label' => $formElementConfiguration['label'], + 'description' => $formElementConfiguration['description'] ?? '', + 'requestType' => 'event', + 'event' => 'typo3:form:insert-element-click', + 'sorting' => $formElementConfiguration['groupSorting'], + 'icon' => $formElementConfiguration['iconIdentifier'], + ]; + } + $formGroups = []; + foreach ($prototypeConfiguration['formEditor']['formElementGroups'] ?? [] as $groupName => $groupConfiguration) { + if (!isset($formElementsByGroup[$groupName])) { + continue; + } + usort($formElementsByGroup[$groupName], static function ($a, $b) { + return $a['sorting'] - $b['sorting']; + }); + $groupConfiguration = $this->translationService->translateValuesRecursive( + $groupConfiguration, + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + $formGroups[$groupName] = [ + 'identifier' => $groupName, + 'items' => $formElementsByGroup[$groupName], + 'label' => $groupConfiguration['label'], + ]; + } + return $formGroups; + } + + /** + * Reduce the YAML settings by the 'formEditor' keyword. + */ + protected function getFormEditorDefinitions(array $prototypeConfiguration): array + { + $formEditorDefinitions = []; + foreach ([$prototypeConfiguration, $prototypeConfiguration['formEditor']] as $configuration) { + foreach ($configuration as $firstLevelItemKey => $firstLevelItemValue) { + if (!str_ends_with($firstLevelItemKey, 'Definition')) { + continue; + } + $reducedKey = substr($firstLevelItemKey, 0, -10); + foreach ($firstLevelItemValue as $formEditorDefinitionKey => $formEditorDefinitionValue) { + if (isset($formEditorDefinitionValue['formEditor'])) { + $formEditorDefinitionValue = array_intersect_key($formEditorDefinitionValue, array_flip(['formEditor'])); + $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue['formEditor']; + } else { + $formEditorDefinitions[$reducedKey][$formEditorDefinitionKey] = $formEditorDefinitionValue; + } + } + } + } + $formEditorDefinitions = ArrayUtility::reIndexNumericArrayKeysRecursive($formEditorDefinitions); + $formEditorDefinitions = $this->formEditorEnrichmentService->enrichFormEditorDefinitions($formEditorDefinitions); + return $this->translationService->translateValuesRecursive( + $formEditorDefinitions, + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + } + + /** + * Initialize ModuleTemplate and register docheader icons. + */ + protected function initializeModuleTemplate(RequestInterface $request, string $returnUrl = ''): ModuleTemplate + { + $moduleTemplate = $this->moduleTemplateFactory->create($request); + $getVars = $request->getArguments(); + if (isset($getVars['action']) && $getVars['action'] === 'index') { + $closeUrl = $returnUrl !== '' ? $returnUrl : (string)$this->coreUriBuilder->buildUriFromRoute('web_FormFormbuilder'); + $closeButton = $this->componentFactory->createCloseButton($closeUrl) + ->setDataAttributes(['identifier' => 'closeButton']) + ->setClasses('formeditor-element-close-form-button hidden'); + $moduleTemplate->addButtonToButtonBar($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 2); + $saveButton = $this->componentFactory->createInputButton() + ->setDataAttributes(['identifier' => 'saveButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.save_button')) + ->setName('formeditor-save-form') + ->setValue('save') + ->setClasses('formeditor-element-save-form-button hidden') + ->setIcon($this->iconFactory->getIcon('actions-document-save', IconSize::SMALL)) + ->setShowLabelText(true); + $moduleTemplate->addButtonToButtonBar($saveButton, ButtonBar::BUTTON_POSITION_LEFT, 3); + $undoButton = $this->componentFactory->createInputButton() + ->setDataAttributes(['identifier' => 'undoButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.undo_button')) + ->setName('formeditor-undo-form') + ->setValue('undo') + ->setClasses('formeditor-element-undo-form-button hidden disabled') + ->setIcon($this->iconFactory->getIcon('actions-edit-undo', IconSize::SMALL)); + $moduleTemplate->addButtonToButtonBar($undoButton, ButtonBar::BUTTON_POSITION_LEFT, 5); + $redoButton = $this->componentFactory->createInputButton() + ->setDataAttributes(['identifier' => 'redoButton']) + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formEditor.redo_button')) + ->setName('formeditor-redo-form') + ->setValue('redo') + ->setClasses('formeditor-element-redo-form-button hidden disabled') + ->setIcon($this->iconFactory->getIcon('actions-edit-redo', IconSize::SMALL)); + $moduleTemplate->addButtonToButtonBar($redoButton, ButtonBar::BUTTON_POSITION_LEFT, 5); + } + return $moduleTemplate; + } + + /** + * Render the form editor templates. + */ + protected function renderFormEditorTemplates(array $prototypeConfiguration, array $formEditorDefinitions): string + { + $fluidConfiguration = $prototypeConfiguration['formEditor']['formEditorFluidConfiguration'] ?? null; + $formEditorPartials = $prototypeConfiguration['formEditor']['formEditorPartials'] ?? null; + if (!isset($fluidConfiguration['templatePathAndFilename'])) { + throw new RenderingException('The option templatePathAndFilename must be set.', 1485636499); + } + if (!isset($fluidConfiguration['layoutRootPaths']) || !is_array($fluidConfiguration['layoutRootPaths'])) { + throw new RenderingException('The option layoutRootPaths must be set.', 1480294721); + } + if (!isset($fluidConfiguration['partialRootPaths']) || !is_array($fluidConfiguration['partialRootPaths'])) { + throw new RenderingException('The option partialRootPaths must be set.', 1480294722); + } + + $elementsCategories = $this->getInsertRenderablesPanelConfiguration($prototypeConfiguration, $formEditorDefinitions['formElements']); + $pagesCategories = $this->getInsertRenderablesPanelConfiguration($prototypeConfiguration, $formEditorDefinitions['formElements'], true); + $viewFactoryData = new ViewFactoryData( + templatePathAndFilename: $fluidConfiguration['templatePathAndFilename'], + partialRootPaths: $fluidConfiguration['partialRootPaths'], + layoutRootPaths: $fluidConfiguration['layoutRootPaths'], + request: $this->request, + ); + $view = $this->viewFactory->create($viewFactoryData); + $view->assignMultiple([ + 'elementsCategoriesJson' => GeneralUtility::jsonEncodeForHtmlAttribute($elementsCategories, false), + 'pagesCategoriesJson' => GeneralUtility::jsonEncodeForHtmlAttribute($pagesCategories, false), + 'formEditorPartials' => $formEditorPartials, + ]); + return $view->render(); + } + + /** + * @todo move this to FormDefinitionConversionService + */ + protected function transformFormDefinitionForFormEditor(array $prototypeConfiguration, array $formDefinition, string $formPersistenceIdentifier): array + { + /** @var array> $multiValueFormElementProperties */ + $multiValueFormElementProperties = []; + /** @var array> $multiValueFinisherProperties */ + $multiValueFinisherProperties = []; + foreach ($prototypeConfiguration['formElementsDefinition'] as $type => $configuration) { + if (!isset($configuration['formEditor']['editors'])) { + continue; + } + foreach ($configuration['formEditor']['editors'] as $editorConfiguration) { + if (($editorConfiguration['templateName'] ?? '') === 'Inspector-PropertyGridEditor') { + $multiValueFormElementProperties[$type][] = $editorConfiguration['propertyPath']; + } + } + } + foreach ($prototypeConfiguration['formElementsDefinition']['Form']['formEditor']['propertyCollections']['finishers'] ?? [] as $configuration) { + if (!isset($configuration['editors'])) { + continue; + } + foreach ($configuration['editors'] as $editorConfiguration) { + if (($editorConfiguration['templateName'] ?? '') === 'Inspector-PropertyGridEditor') { + $multiValueFinisherProperties[$configuration['identifier']][] = $editorConfiguration['propertyPath']; + } + } + } + $formDefinition = $this->filterEmptyArrays($formDefinition); + $formDefinition = $this->migrateEmailFinisherRecipients($formDefinition); + + $formDefinition = $this->transformMultiValuePropertiesForFormEditor( + $formDefinition, + 'type', + $multiValueFormElementProperties + ); + $formDefinition = $this->transformMultiValuePropertiesForFormEditor( + $formDefinition, + 'identifier', + $multiValueFinisherProperties + ); + + $rtePropertyPaths = $this->formDefinitionConversionService->extractRtePropertyPaths($prototypeConfiguration); + if ($rtePropertyPaths !== []) { + $formDefinition = $this->formDefinitionConversionService->transformRteContentForRichTextEditor( + $formDefinition, + $rtePropertyPaths + ); + } + + $formDefinition = $this->formDefinitionConversionService->sanitizeHtml($formDefinition, $rtePropertyPaths); + $formDefinition = $this->formDefinitionConversionService->addHmacData($formDefinition, $formPersistenceIdentifier); + return $this->formDefinitionConversionService->migrateFinisherConfiguration($formDefinition); + } + + /** + * Some data needs a transformation before it can be used by the + * form editor. This rules for multivalue elements like select + * elements. To ensure the right sorting if the data goes into + * javascript, we need to do transformations: + * + * [ + * '5' => '5', + * '4' => '4', + * '3' => '3' + * ] + * + * + * This method transform this into: + * + * [ + * [ + * _label => '5' + * _value => 5 + * ], + * [ + * _label => '4' + * _value => 4 + * ], + * [ + * _label => '3' + * _value => 3 + * ], + * ] + * + * @param array> $multiValueProperties + */ + protected function transformMultiValuePropertiesForFormEditor( + array $formDefinition, + string $identifierProperty, + array $multiValueProperties + ): array { + $output = $formDefinition; + foreach ($formDefinition as $key => $value) { + $identifier = $value[$identifierProperty] ?? null; + if (is_string($identifier) && array_key_exists($identifier, $multiValueProperties)) { + $multiValuePropertiesForIdentifier = $multiValueProperties[$identifier]; + foreach ($multiValuePropertiesForIdentifier as $multiValueProperty) { + if (!ArrayUtility::isValidPath($value, $multiValueProperty, '.')) { + continue; + } + $multiValuePropertyData = ArrayUtility::getValueByPath($value, $multiValueProperty, '.'); + if (!is_array($multiValuePropertyData)) { + continue; + } + $newMultiValuePropertyData = []; + foreach ($multiValuePropertyData as $k => $v) { + $newMultiValuePropertyData[] = [ + '_label' => $v, + '_value' => $k, + ]; + } + $value = ArrayUtility::setValueByPath($value, $multiValueProperty, $newMultiValuePropertyData, '.'); + } + } + $output[$key] = $value; + if (is_array($value)) { + $output[$key] = $this->transformMultiValuePropertiesForFormEditor( + $value, + $identifierProperty, + $multiValueProperties + ); + } + } + return $output; + } + + /** + * Remove keys from an array if the key value is an empty array + */ + protected function filterEmptyArrays(array $array): array + { + foreach ($array as $key => $value) { + if (!is_array($value)) { + continue; + } + if (empty($value)) { + unset($array[$key]); + continue; + } + $array[$key] = $this->filterEmptyArrays($value); + if (empty($array[$key])) { + unset($array[$key]); + } + } + return $array; + } + + /** + * Migrate single recipient options to their list successors + */ + protected function migrateEmailFinisherRecipients(array $formDefinition): array + { + foreach ($formDefinition['finishers'] ?? [] as $i => $finisherConfiguration) { + if (!in_array($finisherConfiguration['identifier'], ['EmailToSender', 'EmailToReceiver'], true)) { + continue; + } + $recipientAddress = $finisherConfiguration['options']['recipientAddress'] ?? ''; + $recipientName = $finisherConfiguration['options']['recipientName'] ?? ''; + $carbonCopyAddress = $finisherConfiguration['options']['carbonCopyAddress'] ?? ''; + $blindCarbonCopyAddress = $finisherConfiguration['options']['blindCarbonCopyAddress'] ?? ''; + $replyToAddress = $finisherConfiguration['options']['replyToAddress'] ?? ''; + if (!empty($recipientAddress)) { + $finisherConfiguration['options']['recipients'][$recipientAddress] = $recipientName; + } + if (!empty($carbonCopyAddress)) { + $finisherConfiguration['options']['carbonCopyRecipients'][$carbonCopyAddress] = ''; + } + if (!empty($blindCarbonCopyAddress)) { + $finisherConfiguration['options']['blindCarbonCopyRecipients'][$blindCarbonCopyAddress] = ''; + } + if (!empty($replyToAddress)) { + $finisherConfiguration['options']['replyToRecipients'][$replyToAddress] = ''; + } + unset( + $finisherConfiguration['options']['recipientAddress'], + $finisherConfiguration['options']['recipientName'], + $finisherConfiguration['options']['carbonCopyAddress'], + $finisherConfiguration['options']['blindCarbonCopyAddress'], + $finisherConfiguration['options']['replyToAddress'] + ); + $formDefinition['finishers'][$i] = $finisherConfiguration; + } + return $formDefinition; + } + + protected function flushPageCache(string $formPersistenceIdentifier): void + { + $pageIdList = []; + $referenceRows = $this->databaseService->getReferencesByPersistenceIdentifier($formPersistenceIdentifier); + foreach ($referenceRows as $referenceRow) { + $record = BackendUtility::getRecord($referenceRow['tablename'], $referenceRow['recuid']); + if (!$record) { + continue; + } + $pageIdList[] = $record['pid']; + } + + foreach (array_unique($pageIdList) as $pageId) { + $this->cacheManager->flushCachesInGroupByTag('pages', 'pageId_' . $pageId); + } + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Controller/FormFrontendController.php b/Classes/Controller/FormFrontendController.php new file mode 100644 index 0000000..075ca8b --- /dev/null +++ b/Classes/Controller/FormFrontendController.php @@ -0,0 +1,156 @@ +settings['persistenceIdentifier'])) { + $typoScriptSettings = $this->configurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $formDefinition = $this->formPersistenceManager->load($this->settings['persistenceIdentifier'], $typoScriptSettings, $this->request); + $formDefinition['persistenceIdentifier'] = $this->settings['persistenceIdentifier']; + $formDefinition = $this->overrideByFlexFormSettings($formDefinition); + $formDefinition = ArrayUtility::setValueByPath($formDefinition, 'renderingOptions._originalIdentifier', $formDefinition['identifier'], '.'); + $formDefinition['identifier'] .= '-' . ($this->request->getAttribute('currentContentObject')?->data['uid'] ?? ''); + } + $this->view->assign('formConfiguration', $formDefinition); + return $this->htmlResponse(); + } + + /** + * This method is used to display all pages / finishers except the + * first page because its non cached. + * + * @internal + */ + public function performAction(): ResponseInterface + { + return new ForwardResponse('render'); + } + + /** + * Override the formDefinition with additional data from the Flexform + * settings. For now, only finisher settings are overridable. + */ + protected function overrideByFlexFormSettings(array $formDefinition): array + { + $flexFormData = $this->request->getAttribute('currentContentObject')?->data['pi_flexform'] ?? []; + if (is_string($flexFormData) && $flexFormData !== '') { + $flexFormData = GeneralUtility::xml2array($flexFormData); + } + if (!is_array($flexFormData) || $flexFormData === []) { + return $formDefinition; + } + if (isset($formDefinition['finishers'])) { + $prototypeName = $formDefinition['prototypeName'] ?? 'standard'; + $prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($prototypeName); + foreach ($formDefinition['finishers'] as $index => $formFinisherDefinition) { + $finisherIdentifier = $formFinisherDefinition['identifier']; + $sheetIdentifier = $this->getFlexformSheetIdentifier($formDefinition, $prototypeName, $finisherIdentifier); + $flexFormSheetSettings = $this->getFlexFormSettingsFromSheet($flexFormData, $sheetIdentifier); + if (($this->settings['overrideFinishers'] ?? false) && isset($flexFormSheetSettings['finishers'][$finisherIdentifier])) { + $prototypeFinisherDefinition = $prototypeConfiguration['finishersDefinition'][$finisherIdentifier] ?? []; + $converterDto = GeneralUtility::makeInstance( + FlexFormFinisherOverridesConverterDto::class, + $prototypeFinisherDefinition, + $formFinisherDefinition, + $finisherIdentifier, + $flexFormSheetSettings + ); + // Iterate over all `prototypes..finishersDefinition..FormEngine.elements` values + GeneralUtility::makeInstance(ArrayProcessor::class, $prototypeFinisherDefinition['FormEngine']['elements'])->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'modifyFinisherOptionsFromFlexFormOverrides', + '^(.*)(?:\.config\.type|\.section)$', + GeneralUtility::makeInstance(FinisherOptionsFlexFormOverridesConverter::class, $converterDto) + ) + ); + $formDefinition['finishers'][$index] = $converterDto->getFinisherDefinition(); + } + } + } + return $formDefinition; + } + + protected function getFlexformSheetIdentifier(array $formDefinition, string $prototypeName, string $finisherIdentifier): string + { + return md5( + implode('', [ + $formDefinition['persistenceIdentifier'], + $prototypeName, + $formDefinition['identifier'], + $finisherIdentifier, + ]) + ); + } + + protected function getFlexFormSettingsFromSheet(array $flexForm, string $sheetIdentifier): array + { + $sheetData = []; + $sheetData['data'] = array_filter( + $flexForm['data'] ?? [], + static function ($key) use ($sheetIdentifier) { + return $key === $sheetIdentifier; + }, + ARRAY_FILTER_USE_KEY + ); + if (empty($sheetData['data'])) { + return []; + } + $sheetDataXml = $this->flexFormTools->flexArray2Xml($sheetData); + return $this->flexFormTools->convertFlexFormContentToArray($sheetDataXml)['settings'] ?? []; + } +} diff --git a/Classes/Controller/FormManagerController.php b/Classes/Controller/FormManagerController.php new file mode 100644 index 0000000..46bab0f --- /dev/null +++ b/Classes/Controller/FormManagerController.php @@ -0,0 +1,569 @@ +getFormSettings(); + $hasForms = $this->formPersistenceManager->hasForms([]); + $searchCriteria = new SearchCriteria(searchTerm: trim($searchTerm), orderField: $orderField, orderDirection: $orderDirection); + $returnUrl = $this->request->getAttribute('normalizedParams')->getRequestUri(); + $forms = $hasForms ? $this->getAvailableFormDefinitions($formSettings, $searchCriteria, $returnUrl) : []; + $arrayPaginator = new ArrayPaginator($forms, $page, self::PAGINATION_MAX); + $pagination = new SimplePagination($arrayPaginator); + $moduleTemplate = $this->initializeModuleTemplate($this->request, $page, $searchTerm); + $moduleTemplate->assignMultiple([ + 'paginator' => $arrayPaginator, + 'pagination' => $pagination, + 'searchTerm' => $searchTerm, + 'orderField' => $searchCriteria->orderField, + 'orderDirection' => $searchCriteria->orderDirection, + 'hasForms' => $hasForms, + 'stylesheets' => $formSettings['formManager']['stylesheets'], + 'formManagerAppInitialData' => json_encode($this->getFormManagerAppInitialData($formSettings)), + ]); + $javaScriptModules = array_map( + static fn(string $name) => JavaScriptModuleInstruction::create($name), + array_filter( + $formSettings['formManager']['dynamicJavaScriptModules'] ?? [], + fn(string $name) => in_array($name, self::JS_MODULE_NAMES, true), + ARRAY_FILTER_USE_KEY + ) + ); + $this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction( + JavaScriptModuleInstruction::create('@typo3/form/backend/helper.js', 'Helper') + ->invoke('dispatchFormManager', $javaScriptModules, $this->getFormManagerAppInitialData($formSettings)) + ); + array_map($this->pageRenderer->getJavaScriptRenderer()->addJavaScriptModuleInstruction(...), $javaScriptModules); + $moduleTemplate->setModuleClass($this->request->getPluginName() . '_' . $this->request->getControllerName()); + $moduleTemplate->setFlashMessageQueue($this->getFlashMessageQueue()); + $moduleTemplate->setTitle( + $this->getLanguageService()->translate('title', 'form.module') + ); + return $moduleTemplate->renderResponse('Backend/FormManager/Index'); + } + + /** + * Initialize the "create" action. + * This action uses the Fluid JsonView::class as view. + */ + protected function initializeCreateAction(): void + { + $this->assertAllowedHttpMethod($this->request, 'POST'); + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Creates a new Form and redirects to the Form Editor + * + * @throws FormException + * @throws PersistenceManagerException + */ + protected function createAction(string $formName, string $templatePath, string $prototypeName, string $storage, string $storageLocation): ResponseInterface + { + $formSettings = $this->getFormSettings(); + if (!$this->formPersistenceManager->isAllowedStorageLocation($storageLocation)) { + throw new PersistenceManagerException(sprintf('Save to storage location "%s" is not allowed', $storageLocation), 1614500657); + } + if (!$this->isValidTemplatePath($formSettings, $prototypeName, $templatePath)) { + throw new FormException(sprintf('The template path "%s" is not allowed', $templatePath), 1329233410); + } + if (empty($formName)) { + throw new FormException('No form name', 1472312204); + } + $templatePath = GeneralUtility::getFileAbsFileName($templatePath); + $form = $this->yamlSource->load([$templatePath]); + $form['label'] = $formName; + $form['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName)); + $form['prototypeName'] = $prototypeName; + $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($storage, $form['identifier'], $storageLocation); + $event = $this->eventDispatcher->dispatch( + new BeforeFormIsCreatedEvent($formPersistenceIdentifier, $form, $this->request) + ); + $formPersistenceIdentifier = $event->formPersistenceIdentifier; + $form = $event->form; + $form = ArrayUtility::stripTagsFromValuesRecursive($form); + try { + $formIdentifier = $this->formPersistenceManager->save($formPersistenceIdentifier, $form, [], $storageLocation); + $response = [ + 'status' => 'success', + 'url' => (string)$this->coreUriBuilder->buildUriFromRoute('form_editor', ['formPersistenceIdentifier' => $formIdentifier->identifier]), + ]; + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + // createAction uses the Extbase JsonView::class. + // That's why we have to set the view variables in this way. + /** @var JsonView $view */ + $view = $this->view; + $view->assign('response', $response); + $view->setVariablesToRender([ + 'response', + ]); + return $this->jsonResponse(); + } + + /** + * Initialize the duplicate action. + * This action uses the Fluid JsonView::class as view. + */ + protected function initializeDuplicateAction(): void + { + $this->assertAllowedHttpMethod($this->request, 'POST'); + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Duplicates a given formDefinition and redirects to the Form Editor + * + * @throws PersistenceManagerException + */ + protected function duplicateAction(string $formName, string $formPersistenceIdentifier, string $storage, string $storageLocation): ResponseInterface + { + if (!$this->formPersistenceManager->isAllowedStorageLocation($storageLocation)) { + throw new PersistenceManagerException(sprintf('Save to storage location "%s" is not allowed', $storageLocation), 1614500658); + } + if (!$this->formPersistenceManager->isAllowedPersistenceIdentifier($formPersistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('Read of "%s" is not allowed', $formPersistenceIdentifier), 1614500659); + } + $formToDuplicate = $this->formPersistenceManager->load($formPersistenceIdentifier); + $formToDuplicate['label'] = $formName; + $formToDuplicate['identifier'] = $this->formPersistenceManager->getUniqueIdentifier($this->convertFormNameToIdentifier($formName)); + $formPersistenceIdentifier = $this->formPersistenceManager->getUniquePersistenceIdentifier($storage, $formToDuplicate['identifier'], $storageLocation); + $event = $this->eventDispatcher->dispatch( + new BeforeFormIsDuplicatedEvent($formPersistenceIdentifier, $formToDuplicate, $this->request) + ); + $formPersistenceIdentifier = $event->formPersistenceIdentifier; + $formToDuplicate = $event->form; + $formToDuplicate = ArrayUtility::stripTagsFromValuesRecursive($formToDuplicate); + try { + $formIdentifier = $this->formPersistenceManager->save($formPersistenceIdentifier, $formToDuplicate, [], $storageLocation); + $response = [ + 'status' => 'success', + 'url' => (string)$this->coreUriBuilder->buildUriFromRoute('form_editor', ['formPersistenceIdentifier' => $formIdentifier->identifier]), + ]; + } catch (PersistenceManagerException $e) { + $response = [ + 'status' => 'error', + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + ]; + } + // createAction uses the Extbase JsonView::class. + // That's why we have to set the view variables in this way. + /** @var JsonView $view */ + $view = $this->view; + $view->assign('response', $response); + $view->setVariablesToRender([ + 'response', + ]); + return $this->jsonResponse(); + } + + /** + * Initialize the references action. + * This action uses the Fluid JsonView::class as view. + */ + protected function initializeReferencesAction(): void + { + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Show references to this persistence identifier + * + * @throws PersistenceManagerException + */ + protected function referencesAction(string $formPersistenceIdentifier): ResponseInterface + { + if (!$this->formPersistenceManager->isAllowedPersistenceIdentifier($formPersistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('Access to "%s" is not allowed', $formPersistenceIdentifier), 1614500661); + } + // referencesAction uses the extbase JsonView::class. + // That's why we have to set the view variables in this way. + /** @var JsonView $view */ + $view = $this->view; + $view->assign('references', $this->getProcessedReferencesRows($formPersistenceIdentifier)); + $view->assign('formPersistenceIdentifier', $formPersistenceIdentifier); + $view->setVariablesToRender([ + 'references', + 'formPersistenceIdentifier', + ]); + return $this->jsonResponse(); + } + + protected function initializeDeleteAction(): void + { + $this->assertAllowedHttpMethod($this->request, 'POST'); + $this->defaultViewObjectName = JsonView::class; + } + + /** + * Delete a formDefinition identified by the $formPersistenceIdentifier. + * + * @throws PersistenceManagerException + */ + protected function deleteAction(string $formPersistenceIdentifier): ResponseInterface + { + $formSettings = $this->getFormSettings(); + if (!$this->formPersistenceManager->isAllowedPersistenceIdentifier($formPersistenceIdentifier)) { + throw new PersistenceManagerException(sprintf('Delete "%s" is not allowed', $formPersistenceIdentifier), 1768562524); + } + + $hasReferences = !empty($this->databaseService->getReferencesByPersistenceIdentifier($formPersistenceIdentifier)); + + if ($hasReferences) { + $response = $this->getErrorResponseForDeleteAction($formSettings, $formPersistenceIdentifier); + } else { + $event = $this->eventDispatcher->dispatch( + new BeforeFormIsDeletedEvent($formPersistenceIdentifier, $this->request) + ); + if ($event->preventDeletion) { + $response = $this->getErrorResponseForDeleteAction($formSettings, $formPersistenceIdentifier); + } else { + $this->formPersistenceManager->delete($formPersistenceIdentifier, []); + $response = [ + 'status' => 'success', + 'url' => $this->uriBuilder->uriFor('index', [], 'FormManager'), + ]; + } + } + + // deleteAction uses the extbase JsonView::class. + // That's why we have to set the view variables in this way. + /** @var JsonView $view */ + $view = $this->view; + $view->assign('response', $response); + $view->setVariablesToRender([ + 'response', + ]); + return $this->jsonResponse(); + } + + protected function getErrorResponseForDeleteAction(array $formSettings, string $formPersistenceIdentifier): array + { + $controllerConfiguration = $this->translationService->translateValuesRecursive( + $formSettings['formManager']['controller'], + $formSettings['formManager']['translationFiles'] ?? [] + ); + return [ + 'status' => 'error', + 'title' => $controllerConfiguration['deleteAction']['errorTitle'], + 'message' => sprintf($controllerConfiguration['deleteAction']['errorMessage'], $formPersistenceIdentifier), + ]; + } + + protected function getFormSettings(): array + { + $typoScriptSettings = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $formSettings = $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, false); + if (!isset($formSettings['formManager'])) { + // Config sub array formManager is crucial and should always exist. If it does + // not, this indicates an issue in config loading logic. Except in this case. + throw new \LogicException('Configuration could not be loaded', 1723717461); + } + return $formSettings; + } + + /** + * Returns the json encoded data which is used by the form editor + * JavaScript app. + */ + protected function getFormManagerAppInitialData(array $formSettings): array + { + $formManagerAppInitialData = [ + 'selectablePrototypesConfiguration' => $formSettings['formManager']['selectablePrototypesConfiguration'], + 'endpoints' => [ + 'create' => $this->uriBuilder->uriFor('create'), + 'duplicate' => $this->uriBuilder->uriFor('duplicate'), + 'delete' => $this->uriBuilder->uriFor('delete'), + 'references' => $this->uriBuilder->uriFor('references'), + ], + 'accessibleStorageAdapters' => $this->formPersistenceManager->getAccessibleStorageAdapters(), + ]; + $formManagerAppInitialData = ArrayUtility::reIndexNumericArrayKeysRecursive($formManagerAppInitialData); + return $this->translationService->translateValuesRecursive( + $formManagerAppInitialData, + $formSettings['formManager']['translationFiles'] ?? [] + ); + } + + /** + * List all formDefinitions which can be loaded through form persistence + * manager. Enrich this data by a reference counter. + */ + protected function getAvailableFormDefinitions(array $formSettings, SearchCriteria $searchCriteria, string $returnUrl = ''): array + { + $availableFormDefinitions = []; + + foreach ($this->formPersistenceManager->listForms($formSettings, $searchCriteria) as $formMetadata) { + + if ($formMetadata->persistenceIdentifier && !$formMetadata->invalid && !$formMetadata->readOnly) { + $editUrl = (string)$this->coreUriBuilder->buildUriFromRoute( + 'form_editor', + array_filter([ + 'formPersistenceIdentifier' => $formMetadata->persistenceIdentifier, + 'returnUrl' => $returnUrl, + ]) + ); + $formMetadata = $formMetadata->withEditUrl($editUrl); + } + + $actions = $this->getRecordActions($formMetadata->persistenceIdentifier); + $formMetadata = $formMetadata->withActions($actions); + + if ($searchCriteria->searchTerm === '' + || $this->valueContainsSearchTerm($formMetadata->name, $searchCriteria->searchTerm) + || ($formMetadata->persistenceIdentifier && $this->valueContainsSearchTerm($formMetadata->persistenceIdentifier, $searchCriteria->searchTerm)) + ) { + $availableFormDefinitions[] = $formMetadata; + } + } + + return $availableFormDefinitions; + } + + protected function valueContainsSearchTerm(string $value, string $searchTerm): bool + { + return str_contains(strtolower($value), strtolower($searchTerm)); + } + + /** + * Returns an array with information about the references for a + * formDefinition identified by $persistenceIdentifier. + */ + protected function getProcessedReferencesRows(string $persistenceIdentifier): array + { + if (empty($persistenceIdentifier)) { + throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1477071939); + } + $references = []; + $referenceRows = $this->databaseService->getReferencesByPersistenceIdentifier($persistenceIdentifier); + foreach ($referenceRows as $referenceRow) { + $record = $this->getRecord($referenceRow['tablename'], $referenceRow['recuid']); + if (!$record) { + continue; + } + $pageRecord = $this->getRecord('pages', $record['pid']); + $urlParameters = [ + 'edit' => [ + $referenceRow['tablename'] => [ + $referenceRow['recuid'] => 'edit', + ], + ], + 'module' => 'web_FormFormbuilder', + 'returnUrl' => $this->getModuleUrl('web_FormFormbuilder'), + ]; + $references[] = [ + 'recordPageTitle' => is_array($pageRecord) ? BackendUtility::getRecordTitle('pages', $pageRecord) : '', + 'recordTitle' => BackendUtility::getRecordTitle($referenceRow['tablename'], $record), + 'recordIcon' => $this->iconFactory->getIconForRecord($referenceRow['tablename'], $record, IconSize::SMALL)->render(), + 'recordUid' => $referenceRow['recuid'], + 'recordEditUrl' => $this->getModuleUrl('record_edit', $urlParameters), + ]; + } + return $references; + } + + /** + * Check if a given $templatePath for a given $prototypeName is valid + * and accessible. + * + * Valid template paths has to be configured within + * formManager.selectablePrototypesConfiguration.[('identifier': $prototypeName)].newFormTemplates.[('templatePath': $templatePath)] + */ + protected function isValidTemplatePath(array $formSettings, string $prototypeName, string $templatePath): bool + { + $isValid = false; + foreach ($formSettings['formManager']['selectablePrototypesConfiguration'] as $prototypesConfiguration) { + if ($prototypesConfiguration['identifier'] !== $prototypeName) { + continue; + } + foreach ($prototypesConfiguration['newFormTemplates'] as $templatesConfiguration) { + if ($templatesConfiguration['templatePath'] !== $templatePath) { + continue; + } + $isValid = true; + break; + } + } + $templatePath = GeneralUtility::getFileAbsFileName($templatePath); + if (!is_file($templatePath)) { + $isValid = false; + } + return $isValid; + } + + /** + * Returns the record actions + * + * @return array + * @throws RouteNotFoundException + */ + protected function getRecordActions(string $persistenceIdentifier): array + { + if (!MathUtility::canBeInterpretedAsInteger($persistenceIdentifier)) { + return []; + } + + $actions = []; + + // History button + $urlParameters = [ + 'element' => FormDefinitionRepository::TABLE_NAME . ':' . $persistenceIdentifier, + 'returnUrl' => $this->request->getAttribute('normalizedParams')->getRequestUri(), + ]; + $actions['recordHistoryUrl'] = (string)$this->coreUriBuilder->buildUriFromRoute('record_history', $urlParameters); + + return $actions; + } + + /** + * Init ModuleTemplate and register document header buttons + */ + protected function initializeModuleTemplate(ServerRequestInterface $request, int $page, string $searchTerm): ModuleTemplate + { + $moduleTemplate = $this->moduleTemplateFactory->create($request); + // Create new + $addFormButton = $this->componentFactory->createLinkButton() + ->setDataAttributes(['identifier' => 'newForm']) + ->setHref('#') + ->setTitle($this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:formManager.create_new_form')) + ->setShowLabelText(true) + ->setIcon($this->iconFactory->getIcon('actions-plus', IconSize::SMALL)); + $moduleTemplate->addButtonToButtonBar($addFormButton); + // Shortcut + $arguments = []; + if ($searchTerm) { + $arguments['tx_form_web_formformbuilder']['searchTerm'] = $searchTerm; + $arguments['tx_form_web_formformbuilder']['controller'] = 'FormManager'; + } + if ($page > 1) { + $arguments['tx_form_web_formformbuilder']['page'] = $page; + $arguments['tx_form_web_formformbuilder']['controller'] = 'FormManager'; + } + $moduleTemplate->getDocHeaderComponent()->setShortcutContext( + 'web_FormFormbuilder', + $this->getLanguageService()->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:module.shortcut_name'), + $arguments + ); + return $moduleTemplate; + } + + /** + * Returns a form identifier which is the lower cased form name. + */ + protected function convertFormNameToIdentifier(string $formName): string + { + $formName = \Normalizer::normalize($formName) ?: $formName; + $formIdentifier = $this->charsetConverter->utf8_char_mapping($formName); + $formIdentifier = (string)preg_replace('/[^a-zA-Z0-9-_]/', '', $formIdentifier); + return lcfirst($formIdentifier); + } + + /** + * Wrapper used for unit testing. + */ + protected function getRecord(string $table, int $uid): ?array + { + return BackendUtility::getRecord($table, $uid); + } + + /** + * Wrapper used for unit testing. + */ + protected function getModuleUrl(string $moduleName, array $urlParameters = []): string + { + return (string)$this->coreUriBuilder->buildUriFromRoute($moduleName, $urlParameters); + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/DependencyInjection/FormYamlCollectorConfigurator.php b/Classes/DependencyInjection/FormYamlCollectorConfigurator.php new file mode 100644 index 0000000..258e9fd --- /dev/null +++ b/Classes/DependencyInjection/FormYamlCollectorConfigurator.php @@ -0,0 +1,129 @@ +/} with the collector. + * + * Each set directory must contain a {@code config.yaml} + * with the actual form configuration (loaded in both frontend and backend). + * + * Sets whose declared {@code name} in {@code config.yaml} appears in + * {@code $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['form']['disabledSets']} + * are skipped. + * + * @internal + */ +final readonly class FormYamlCollectorConfigurator +{ + public function __construct( + private PackageManager $packageManager, + private LoggerInterface $logger, + ) {} + + /** + * Populates the given {@see FormYamlCollector} with all auto-discovered + * form YAML configurations across all active extensions. + * + * Note: {@see $GLOBALS['TYPO3_CONF_VARS']} is read at service-instantiation + * time (not at DI-compile time), so ext_localconf.php values are available. + */ + public function configure(FormYamlCollector $collector): void + { + // Sets listed here (by their config.yaml "name" field) are excluded from loading. + // Example in ext_localconf.php: + // $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['form']['disabledSets'][] = 'vendor/set-name'; + $disabledSets = (array)($GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['form']['disabledSets'] ?? []); + + foreach ($this->packageManager->getActivePackages() as $package) { + $formConfigPath = $package->getPackagePath() . 'Configuration/Form'; + + if (!is_dir($formConfigPath)) { + continue; + } + + $extensionKey = $package->getPackageKey(); + + try { + $finder = Finder::create() + ->files() + ->depth(1) + ->sortByName() + ->name('config.yaml') + ->in($formConfigPath); + } catch (\InvalidArgumentException) { + // Directory exists but is not traversable + continue; + } + + foreach ($finder as $fileInfo) { + $setDirectory = dirname($fileInfo->getPathname()); + $setDirectoryName = basename($setDirectory); + + try { + $config = Yaml::parseFile($fileInfo->getPathname()) ?? []; + } catch (ParseException $e) { + $this->logger->warning( + 'EXT:form skipped form set: could not parse config.yaml.', + [ + 'file' => $fileInfo->getPathname(), + 'error' => $e->getMessage(), + ] + ); + continue; + } + + if (!is_array($config)) { + $this->logger->warning( + 'EXT:form skipped form set: config.yaml did not return an array.', + ['file' => $fileInfo->getPathname()] + ); + continue; + } + + // Skip disabled sets. Matching is done against the declared "name" in config.yaml + // (e.g. "my-vendor/my-set"), NOT against the directory name, so that renaming + // a set directory does not break the disable list. + $declaredName = (string)($config['name'] ?? ''); + if ($declaredName !== '' && in_array($declaredName, $disabledSets, true)) { + continue; + } + + $priority = (int)($config['priority'] ?? 100); + $virtualBase = 'EXT:' . $extensionKey . '/Configuration/Form/' . $setDirectoryName . '/'; + + $collector->add(new FormYamlConfiguration( + path: $virtualBase . 'config.yaml', + priority: $priority, + setName: $declaredName, + )); + } + } + } +} diff --git a/Classes/Domain/Condition/ConditionProvider.php b/Classes/Domain/Condition/ConditionProvider.php new file mode 100644 index 0000000..ab37531 --- /dev/null +++ b/Classes/Domain/Condition/ConditionProvider.php @@ -0,0 +1,37 @@ +expressionLanguageProviders = [ + FormConditionFunctionsProvider::class, + ]; + } +} diff --git a/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php b/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php new file mode 100644 index 0000000..923ce19 --- /dev/null +++ b/Classes/Domain/Condition/Functions/FormConditionFunctionsProvider.php @@ -0,0 +1,70 @@ +getFormValueFunction(), + $this->getRootFormPropertyFunction(), + ]; + } + + /** + * Shortcut function to access field values + */ + protected function getFormValueFunction(): ExpressionFunction + { + return new ExpressionFunction( + 'getFormValue', + static fn() => null, // Not implemented, we only use the evaluator + static function ($arguments, $field, $default = null) { + return $arguments['formValues'][$field] ?? $default; + } + ); + } + + protected function getRootFormPropertyFunction(): ExpressionFunction + { + return new ExpressionFunction( + 'getRootFormProperty', + static fn() => null, // Not implemented, we only use the evaluator + static function ($arguments, $property) { + $formDefinition = $arguments['formRuntime']->getFormDefinition(); + try { + $value = ObjectAccess::getPropertyPath($formDefinition, $property); + } catch (\Exception) { + $value = null; + } + return $value; + } + ); + } +} diff --git a/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessing.php b/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessing.php new file mode 100644 index 0000000..b458591 --- /dev/null +++ b/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessing.php @@ -0,0 +1,64 @@ +identifier = $identifier; + $this->expression = $expression; + $this->processor = $processor; + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function getExpression(): string + { + return $this->expression; + } + + public function getProcessor(): callable + { + return $this->processor; + } +} diff --git a/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessor.php b/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessor.php new file mode 100644 index 0000000..a8569ab --- /dev/null +++ b/Classes/Domain/Configuration/ArrayProcessing/ArrayProcessor.php @@ -0,0 +1,93 @@ +data = ArrayUtility::flattenPlain($data); + } + + /** + * @param ArrayProcessing[] $processings + */ + public function forEach(...$processings): array + { + $result = []; + + $processings = $this->getValidProcessings($processings); + foreach ($this->data as $key => $value) { + foreach ($processings as $processing) { + // explicitly escaping non-escaped '#' which is used + // as PCRE delimiter in the following processing + $expression = preg_replace( + '/(?getExpression() + ); + + if (preg_match('#' . $expression . '#', $key, $matches)) { + $identifier = $processing->getIdentifier(); + $processor = $processing->getProcessor(); + $result[$identifier] = $result[$identifier] ?? []; + $result[$identifier][$key] = $processor($key, $value, $matches); + } + } + } + + return $result; + } + + /** + * @return ArrayProcessing[] + * @throws ArrayProcessorException + */ + protected function getValidProcessings(array $allProcessings): array + { + $validProcessings = []; + $identifiers = []; + foreach ($allProcessings as $processing) { + if ($processing instanceof ArrayProcessing) { + if (in_array($processing->getIdentifier(), $identifiers, true)) { + throw new ArrayProcessorException( + 'ArrayProcessing identifier must be unique.', + 1528638085 + ); + } + $identifiers[] = $processing->getIdentifier(); + $validProcessings[] = $processing; + } + } + return $validProcessings; + } +} diff --git a/Classes/Domain/Configuration/ConfigurationService.php b/Classes/Domain/Configuration/ConfigurationService.php new file mode 100644 index 0000000..51f3e38 --- /dev/null +++ b/Classes/Domain/Configuration/ConfigurationService.php @@ -0,0 +1,676 @@ +getFormSettings(); + if (!isset($formSettings['prototypes'][$prototypeName])) { + throw new PrototypeNotFoundException(sprintf('The Prototype "%s" was not found.', $prototypeName), 1475924277); + } + return $formSettings['prototypes'][$prototypeName]; + } + + /** + * Return all prototype names which are defined within "formManager.selectablePrototypesConfiguration.*.identifier" + * + * @internal + */ + public function getSelectablePrototypeNamesDefinedInFormEditorSetup(): array + { + $formSettings = $this->getFormSettings(); + $returnValue = GeneralUtility::makeInstance( + ArrayProcessor::class, + $formSettings['formManager']['selectablePrototypesConfiguration'] ?? [] + )->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'selectablePrototypeNames', + '^([\d]+)\.identifier$', + static function ($_, $value) { + return $value; + } + ) + ); + return array_values($returnValue['selectablePrototypeNames'] ?? []); + } + + /** + * Check if a form element property is defined in the form setup. + * If a form element property is defined in the form setup then it + * means that the form element property can be written by the form editor. + * A form element property can be written if the property path is defined within + * the following form editor properties: + * * formElementsDefinition..formEditor.editors..propertyPath + * * formElementsDefinition..formEditor.editors..*.propertyPath + * * formElementsDefinition..formEditor.editors..additionalElementPropertyPaths + * * formElementsDefinition..formEditor.propertyCollections...editors..additionalElementPropertyPaths + * If a form editor property "templateName" is + * "Inspector-PropertyGridEditor" or "Inspector-MultiSelectEditor" or "Inspector-ValidationErrorMessageEditor" + * it means that the form editor property "propertyPath" is interpreted as a so called "multiValueProperty". + * A "multiValueProperty" can contain any subproperties relative to the value from "propertyPath" which are valid. + * If "formElementsDefinition..formEditor.editors..templateName = Inspector-PropertyGridEditor" + * and + * "formElementsDefinition..formEditor.editors..propertyPath = options.xxx" + * then (for example) "options.xxx.yyy" is a valid property path to write. + * If you use a custom form editor "inspector editor" implementation which does not define the writable + * property paths by one of the above described inspector editor properties (e.g "propertyPath") within + * the form setup, you must provide the writable property paths via the + * AfterFormDefinitionValidationConfigurationIsBuiltEvent PSR-14 event. + * + * @internal + */ + public function isFormElementPropertyDefinedInFormEditorSetup(ValidationDto $dto): bool + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $subConfig = $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()] ?? []; + return $this->isPropertyDefinedInFormEditorSetup($dto->getPropertyPath(), $subConfig); + } + + /** + * Check if a form elements finisher|validator property is defined in the form setup. + * If a form elements finisher|validator property is defined in the form setup then it + * means that the form elements finisher|validator property can be written by the form editor. + * A form elements finisher|validator property can be written if the property path is defined within + * the following form editor properties: + * * formElementsDefinition..formEditor.propertyCollections...editors..propertyPath + * * formElementsDefinition..formEditor.propertyCollections...editors..*.propertyPath + * If a form elements finisher|validator property "templateName" is + * "Inspector-PropertyGridEditor" or "Inspector-MultiSelectEditor" or "Inspector-ValidationErrorMessageEditor" + * it means that the form editor property "propertyPath" is interpreted as a so called "multiValueProperty". + * A "multiValueProperty" can contain any subproperties relative to the value from "propertyPath" which are valid. + * If "formElementsDefinition..formEditor.propertyCollections...editors..templateName = Inspector-PropertyGridEditor" + * and + * "formElementsDefinition..formEditor.propertyCollections...editors..propertyPath = options.xxx" + * that (for example) "options.xxx.yyy" is a valid property path to write. + * If you use a custom form elements finisher|validator editor implementation which does not define the writable + * property paths by one of the above described inspector editor properties (e.g "propertyPath") within + * the form setup, you must provide the writable property paths via the + * AfterFormDefinitionValidationConfigurationIsBuiltEvent PSR-14 event. + * + * @internal + */ + public function isPropertyCollectionPropertyDefinedInFormEditorSetup(ValidationDto $dto): bool + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $subConfig = $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()] ?? []; + return $this->isPropertyDefinedInFormEditorSetup($dto->getPropertyPath(), $subConfig); + } + + /** + * If a form element editor has a property called "selectOptions" + * (e.g. editors with templateName "Inspector-SingleSelectEditor" or "Inspector-MultiSelectEditor") + * then only the defined values within the selectOptions are allowed to be written + * by the form editor. + * + * @internal + */ + public function formElementPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup( + ValidationDto $dto + ): bool { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $propertyPath = $this->getBasePropertyPathFromMultiValueFormElementProperty($dto); + return isset( + $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['selectOptions'][$propertyPath] + ); + } + + /** + * Get the "selectOptions" value for a form element property from the form setup. + * + * @throws PropertyException + * @internal + */ + public function getAllowedValuesForFormElementPropertyFromFormEditorSetup( + ValidationDto $dto, + bool $translated = true + ): array { + if (!$this->formElementPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup($dto)) { + throw new PropertyException( + sprintf( + 'No selectOptions found for form element type "%s" and property path "%s"', + $dto->getFormElementType(), + $dto->getPropertyPath() + ), + 1614264312 + ); + } + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $property = $translated ? 'selectOptions' : 'untranslatedSelectOptions'; + $propertyPath = $this->getBasePropertyPathFromMultiValueFormElementProperty($dto); + return $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()][$property][$propertyPath]; + } + + /** + * If a form elements finisher|validator editor has a property called "selectOptions" + * (e.g. editors with templateName "Inspector-SingleSelectEditor" or "Inspector-MultiSelectEditor") + * then only the defined values within the selectOptions are allowed to be written + * by the form editor. + * + * @internal + */ + public function propertyCollectionPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup( + ValidationDto $dto + ): bool { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $propertyPath = $this->getBasePropertyPathFromMultiValuePropertyCollectionElement($dto); + return isset( + $formDefinitionValidationConfiguration['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()]['selectOptions'][$propertyPath] + ); + } + + /** + * Get the "selectOptions" value for a form elements finisher|validator property from the form setup. + * + * @throws PropertyException + * @internal + */ + public function getAllowedValuesForPropertyCollectionPropertyFromFormEditorSetup( + ValidationDto $dto, + bool $translated = true + ): array { + if (!$this->propertyCollectionPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup($dto)) { + throw new PropertyException( + sprintf( + 'No selectOptions found for property collection "%s" and identifier "%s" and property path "%s"', + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier(), + $dto->getPropertyPath() + ), + 1614264313 + ); + } + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $property = $translated ? 'selectOptions' : 'untranslatedSelectOptions'; + $propertyPath = $this->getBasePropertyPathFromMultiValuePropertyCollectionElement($dto); + return $formDefinitionValidationConfiguration['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()][$property][$propertyPath]; + } + + protected function getBasePropertyPathFromMultiValueFormElementProperty(ValidationDto $dto): string + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $propertyPath = $dto->getPropertyPath(); + $multiValueProperties = $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['multiValueProperties'] ?? []; + foreach ($multiValueProperties as $multiValueProperty) { + if (str_starts_with($propertyPath, $multiValueProperty)) { + $propertyPath = $multiValueProperty; + } + } + return $propertyPath; + } + + protected function getBasePropertyPathFromMultiValuePropertyCollectionElement(ValidationDto $dto): string + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $propertyPath = $dto->getPropertyPath(); + $multiValueProperties = $formDefinitionValidationConfiguration['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()]['multiValueProperties'] ?? []; + foreach ($multiValueProperties as $multiValueProperty) { + if (str_starts_with($propertyPath, $multiValueProperty)) { + $propertyPath = $multiValueProperty; + } + } + return $propertyPath; + } + + /** + * Check if a form element property is defined in "predefinedDefaults" in the form setup. + * If a form element property is defined in the "predefinedDefaults" in the form setup then it + * means that the form element property can be written by the form editor. + * A form element default property is defined within the following form editor properties: + * * formElementsDefinition..formEditor.predefinedDefaults. = "default value" + * + * @internal + */ + public function isFormElementPropertyDefinedInPredefinedDefaultsInFormEditorSetup(ValidationDto $dto): bool + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + return isset( + $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['predefinedDefaults'][$dto->getPropertyPath()] + ); + } + + /** + * Get the "predefinedDefaults" value for a form element property from the form setup. + * A form element default property is defined within the following form editor properties: + * * formElementsDefinition..formEditor.predefinedDefaults. = "default value" + * + * @throws PropertyException + * @internal + */ + public function getFormElementPredefinedDefaultValueFromFormEditorSetup(ValidationDto $dto, bool $translated = true): mixed + { + if (!$this->isFormElementPropertyDefinedInPredefinedDefaultsInFormEditorSetup($dto)) { + throw new PropertyException( + sprintf( + 'No predefinedDefaults found for form element type "%s" and property path "%s"', + $dto->getFormElementType(), + $dto->getPropertyPath() + ), + 1528578401 + ); + } + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $property = $translated ? 'predefinedDefaults' : 'untranslatedPredefinedDefaults'; + return $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()][$property][$dto->getPropertyPath()]; + } + + /** + * Check if a form elements finisher|validator property is defined in "predefinedDefaults" in the form setup. + * If a form elements finisher|validator property is defined in "predefinedDefaults" in the form setup then it + * means that the form elements finisher|validator property can be written by the form editor. + * A form elements finisher|validator default property is defined within the following form editor properties: + * * ..formEditor.predefinedDefaults. = "default value" + * + * @internal + */ + public function isPropertyCollectionPropertyDefinedInPredefinedDefaultsInFormEditorSetup(ValidationDto $dto): bool + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + return isset( + $formDefinitionValidationConfiguration['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()]['predefinedDefaults'][$dto->getPropertyPath()] + ); + } + + /** + * Get the "predefinedDefaults" value for a form elements finisher|validator property from the form setup. + * A form elements finisher|validator default property is defined within the following form editor properties: + * * ..formEditor.predefinedDefaults. = "default value" + * + * @throws PropertyException + * @internal + */ + public function getPropertyCollectionPredefinedDefaultValueFromFormEditorSetup(ValidationDto $dto, bool $translated = true): mixed + { + if (!$this->isPropertyCollectionPropertyDefinedInPredefinedDefaultsInFormEditorSetup($dto)) { + throw new PropertyException( + sprintf( + 'No predefinedDefaults found for property collection "%s" and identifier "%s" and property path "%s"', + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier(), + $dto->getPropertyPath() + ), + 1528578402 + ); + } + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + $property = $translated ? 'predefinedDefaults' : 'untranslatedPredefinedDefaults'; + return $formDefinitionValidationConfiguration['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()][$property][$dto->getPropertyPath()]; + } + + /** + * Check if the form element is creatable through the form editor. + * A form element is creatable if the following properties are set: + * * formElementsDefinition..formEditor.group + * * formElementsDefinition..formEditor.groupSorting + * And the value from "formElementsDefinition..formEditor.group" is + * one of the keys within "formEditor.formElementGroups" + * + * @internal + */ + public function isFormElementTypeCreatableByFormEditor(ValidationDto $dto): bool + { + if ($dto->getFormElementType() === 'Form') { + return true; + } + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + return $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['creatable'] ?? false; + } + + /** + * Check if the form elements finisher|validator is creatable through the form editor. + * A form elements finisher|validator is creatable if the following conditions are true: + * "formElementsDefinition..formEditor.editors..templateName = Inspector-FinishersEditor" + * or + * "formElementsDefinition..formEditor.editors..templateName = Inspector-ValidatorsEditor" + * and + * "formElementsDefinition..formEditor.editors..selectOptions..value = " + * + * @internal + */ + public function isPropertyCollectionElementIdentifierCreatableByFormEditor(ValidationDto $dto): bool + { + $formDefinitionValidationConfiguration = $this->buildFormDefinitionValidationConfigurationFromFormEditorSetup( + $dto->getPrototypeName() + ); + return $formDefinitionValidationConfiguration['formElements'][$dto->getFormElementType()]['collections'][$dto->getPropertyCollectionName()][$dto->getPropertyCollectionElementIdentifier()]['creatable'] ?? false; + } + + /** + * Check if the form elements type is defined within the form setup. + * + * @internal + */ + public function isFormElementTypeDefinedInFormSetup(ValidationDto $dto): bool + { + $prototypeConfiguration = $this->getPrototypeConfiguration($dto->getPrototypeName()); + return ArrayUtility::isValidPath( + $prototypeConfiguration, + 'formElementsDefinition.' . $dto->getFormElementType(), + '.' + ); + } + + /** + * @internal + */ + public function getAllBackendTranslationsForTranslationKeys(array $keys, string $prototypeName): array + { + $translations = []; + foreach ($keys as $key) { + if (!is_string($key)) { + continue; + } + $translations[$key] = $this->getAllBackendTranslationsForTranslationKey($key, $prototypeName); + } + return $translations; + } + + public function getAllBackendTranslationsForTranslationKey(string $key, string $prototypeName): array + { + $prototypeConfiguration = $this->getPrototypeConfiguration($prototypeName); + return $this->translationService->translateToAllBackendLanguages( + $key, + [], + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + } + + protected function getFormSettings(): array + { + // @todo: This is needed for extFormConfigurationManager to apply stdWrap on TS configuration. + // Find a way to get rid of this. + $isFrontend = false; + $request = $GLOBALS['TYPO3_REQUEST'] ?? null; + if ($request instanceof ServerRequestInterface) { + $isFrontend = ApplicationType::fromRequest($request)->isFrontend(); + } + // @todo: Note this code relies on the fact that the request has been set to ExtbaseConfigurationManagerInterface already. + $typoScriptSettings = $this->extbaseConfigurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + return $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, $isFrontend, $isFrontend ? $request : null); + } + + /** + * Collect all the form editor configurations which are needed to check if a + * form definition property can be written or not. + */ + protected function buildFormDefinitionValidationConfigurationFromFormEditorSetup(string $prototypeName): array + { + $cacheKey = implode('_', ['buildFormDefinitionValidationConfigurationFromFormEditorSetup', $prototypeName]); + $configuration = $this->getCacheEntry($cacheKey); + if ($configuration === null) { + $prototypeConfiguration = $this->getPrototypeConfiguration($prototypeName); + $extractorDto = GeneralUtility::makeInstance(ExtractorDto::class, $prototypeConfiguration); + GeneralUtility::makeInstance(ArrayProcessor::class, $prototypeConfiguration)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementPropertyPaths', + '^formElementsDefinition\.(.*)\.formEditor\.editors\.([\d]+)\.(propertyPath|.*\.propertyPath)$', + GeneralUtility::makeInstance(PropertyPathsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementAdditionalElementPropertyPaths', + '^formElementsDefinition\.(.*)\.formEditor\.editors\.([\d]+)\.additionalElementPropertyPaths\.([\d]+)', + GeneralUtility::makeInstance(AdditionalElementPropertyPathsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementRelativeMultiValueProperties', + '^formElementsDefinition\.(.*)\.formEditor\.editors\.([\d]+)\.templateName$', + GeneralUtility::makeInstance(MultiValuePropertiesExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementSelectOptions', + '^formElementsDefinition\.(.*)\.formEditor\.editors\.([\d]+)\.selectOptions\.([\d]+)\.value$', + GeneralUtility::makeInstance(SelectOptionsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementPredefinedDefaults', + '^formElementsDefinition\.(.*)\.formEditor\.predefinedDefaults\.(.+)$', + GeneralUtility::makeInstance(PredefinedDefaultsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'formElementCreatable', + '^formElementsDefinition\.(.*)\.formEditor.group$', + GeneralUtility::makeInstance(IsCreatableFormElementExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionCreatable', + '^formElementsDefinition\.(.*)\.formEditor\.editors\.([\d]+)\.templateName$', + GeneralUtility::makeInstance(IsCreatablePropertyCollectionElementExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionPropertyPaths', + '^formElementsDefinition\.(.*)\.formEditor\.propertyCollections\.(finishers|validators)\.([\d]+)\.editors\.([\d]+)\.(propertyPath|.*\.propertyPath)$', + GeneralUtility::makeInstance(CollectionPropertyPathsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionAdditionalElementPropertyPaths', + '^formElementsDefinition\.(.*)\.formEditor\.propertyCollections\.(finishers|validators)\.([\d]+)\.editors\.([\d]+)\.additionalElementPropertyPaths\.([\d]+)', + GeneralUtility::makeInstance(AdditionalElementPropertyPathsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionRelativeMultiValueProperties', + '^formElementsDefinition\.(.*)\.formEditor\.propertyCollections\.(finishers|validators)\.([\d]+)\.editors\.([\d]+)\.templateName$', + GeneralUtility::makeInstance(CollectionMultiValuePropertiesExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionSelectOptions', + '^formElementsDefinition\.(.*)\.formEditor\.propertyCollections\.(finishers|validators)\.([\d]+)\.editors\.([\d]+)\.selectOptions\.([\d]+)\.value$', + GeneralUtility::makeInstance(CollectionSelectOptionsExtractor::class, $extractorDto) + ), + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'propertyCollectionPredefinedDefaults', + '^(validatorsDefinition|finishersDefinition)\.(.*)\.formEditor\.predefinedDefaults\.(.+)$', + GeneralUtility::makeInstance(CollectionPredefinedDefaultsExtractor::class, $extractorDto) + ) + ); + $configuration = $extractorDto->getResult(); + $configuration = $this->translateValues($prototypeConfiguration, $configuration); + $configuration = $this->eventDispatcher + ->dispatch(new AfterFormDefinitionValidationConfigurationIsBuiltEvent($prototypeName, $configuration)) + ->getConfiguration(); + $this->setCacheEntry($cacheKey, $configuration); + } + return $configuration; + } + + protected function isPropertyDefinedInFormEditorSetup(string $propertyPath, array $subConfig): bool + { + if (empty($subConfig)) { + return false; + } + if (in_array($propertyPath, $subConfig['propertyPaths'] ?? [], true) + || in_array($propertyPath, $subConfig['additionalElementPropertyPaths'] ?? [], true) + || in_array($propertyPath, $subConfig['additionalPropertyPaths'] ?? [], true) + ) { + return true; + } + foreach ($subConfig['multiValueProperties'] ?? [] as $relativeMultiValueProperty) { + if (str_starts_with($propertyPath, $relativeMultiValueProperty)) { + return true; + } + } + return false; + } + + protected function translateValues(array $prototypeConfiguration, array $configuration): array + { + if (isset($configuration['formElements'])) { + $configuration['formElements'] = $this->translatePredefinedDefaults( + $prototypeConfiguration, + $configuration['formElements'] + ); + $configuration['formElements'] = $this->translateSelectOptions( + $prototypeConfiguration, + $configuration['formElements'] + ); + } + foreach ($configuration['collections'] ?? [] as $name => $collections) { + $configuration['collections'][$name] = $this->translatePredefinedDefaults($prototypeConfiguration, $collections); + $configuration['collections'][$name] = $this->translateSelectOptions($prototypeConfiguration, $configuration['collections'][$name]); + } + return $configuration; + } + + protected function translatePredefinedDefaults(array $prototypeConfiguration, array $formElements): array + { + foreach ($formElements as $name => $formElement) { + if (!isset($formElement['predefinedDefaults'])) { + continue; + } + $formElement['untranslatedPredefinedDefaults'] = $formElement['predefinedDefaults']; + $formElement['predefinedDefaults'] = $this->translationService->translateValuesRecursive( + $formElement['predefinedDefaults'], + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + $formElements[$name] = $formElement; + } + return $formElements; + } + + protected function translateSelectOptions(array $prototypeConfiguration, array $formElements): array + { + foreach ($formElements as $name => $formElement) { + if (empty($formElement['selectOptions']) || !is_array($formElement['selectOptions'])) { + continue; + } + $formElement['untranslatedSelectOptions'] = $formElement['selectOptions']; + $formElement['selectOptions'] = $this->translationService->translateValuesRecursive( + $formElement['selectOptions'], + $prototypeConfiguration['formEditor']['translationFiles'] ?? [] + ); + $formElements[$name] = $formElement; + } + return $formElements; + } + + protected function getCacheEntry(string $cacheKey): mixed + { + $cacheKey = 'form_' . $cacheKey; + if ($this->runtimeCache->has($cacheKey)) { + return $this->runtimeCache->get($cacheKey); + } + if ($this->assetsCache->has($cacheKey)) { + return $this->assetsCache->get($cacheKey); + } + return null; + } + + protected function setCacheEntry(string $cacheKey, mixed $value): void + { + $cacheKey = 'form_' . $cacheKey; + $this->runtimeCache->set($cacheKey, $value); + $this->assetsCache->set($cacheKey, $value); + } +} diff --git a/Classes/Domain/Configuration/Exception/ArrayProcessorException.php b/Classes/Domain/Configuration/Exception/ArrayProcessorException.php new file mode 100644 index 0000000..19620f0 --- /dev/null +++ b/Classes/Domain/Configuration/Exception/ArrayProcessorException.php @@ -0,0 +1,25 @@ +converterDto = $converterDto; + } +} diff --git a/Classes/Domain/Configuration/FlexformConfiguration/Processors/FinisherOptionGenerator.php b/Classes/Domain/Configuration/FlexformConfiguration/Processors/FinisherOptionGenerator.php new file mode 100644 index 0000000..9a84e07 --- /dev/null +++ b/Classes/Domain/Configuration/FlexformConfiguration/Processors/FinisherOptionGenerator.php @@ -0,0 +1,98 @@ +converterDto->getFinisherIdentifier(); + $finisherDefinitionFromSetup = $this->converterDto->getFinisherDefinitionFromSetup(); + $finisherDefinitionFromFormDefinition = $this->converterDto->getFinisherDefinitionFromFormDefinition(); + + try { + $elementConfiguration = ArrayUtility::getValueByPath( + $finisherDefinitionFromSetup['FormEngine']['elements'], + $optionKey, + '.' + ); + } catch (MissingArrayPathException $exception) { + return; + } + + // use the option value from the ext:form setup from the current finisher as default value + try { + $optionValue = ArrayUtility::getValueByPath( + $finisherDefinitionFromSetup, + sprintf('options.%s', $optionKey), + '.' + ); + } catch (MissingArrayPathException $exception) { + $optionValue = null; + } + + // use the option value from the form definition from the current finisher (if exists) as default value + try { + $optionValue = ArrayUtility::getValueByPath( + $finisherDefinitionFromFormDefinition, + sprintf('options.%s', $optionKey), + '.' + ); + } catch (MissingArrayPathException $exception) { + } + + if (isset($elementConfiguration['config'])) { + $elementConfiguration['config']['default'] = $optionValue; + } + + $languageService = $this->getLanguageService(); + $elementConfiguration['label'] = (string)($elementConfiguration['label'] ?? ''); + if (empty($optionValue)) { + $optionValue = $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:empty'); + } elseif (is_array($optionValue)) { + $optionValue = implode(',', $optionValue); + } + $elementConfiguration['label'] .= sprintf(' (%s: "%s")', $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:default'), $optionValue); + + $sheetElements = $this->converterDto->getResult(); + $sheetElements['settings.finishers.' . $finisherIdentifier . '.' . $optionKey] = $elementConfiguration; + + $this->converterDto->setResult($sheetElements); + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorDto.php b/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorDto.php new file mode 100644 index 0000000..d843b4c --- /dev/null +++ b/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorDto.php @@ -0,0 +1,83 @@ +finisherIdentifier = $finisherIdentifier; + $this->finisherDefinitionFromSetup = $finisherDefinitionFromSetup; + $this->finisherDefinitionFromFormDefinition = $finisherDefinitionFromFormDefinition; + } + + public function getFinisherIdentifier(): string + { + return $this->finisherIdentifier; + } + + public function getFinisherDefinitionFromSetup(): array + { + return $this->finisherDefinitionFromSetup; + } + + public function getFinisherDefinitionFromFormDefinition(): array + { + return $this->finisherDefinitionFromFormDefinition; + } + + public function getResult(): array + { + return $this->result; + } + + public function setResult(array $result): ProcessorDto + { + $this->result = $result; + + return $this; + } +} diff --git a/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorInterface.php b/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorInterface.php new file mode 100644 index 0000000..ac72fc7 --- /dev/null +++ b/Classes/Domain/Configuration/FlexformConfiguration/Processors/ProcessorInterface.php @@ -0,0 +1,33 @@ +converterDto = $converterDto; + $this->sessionToken = $sessionToken; + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataConverter.php b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataConverter.php new file mode 100644 index 0000000..369cf3b --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataConverter.php @@ -0,0 +1,94 @@ +" as a sibling of the property key. + * "_orig_" is an array which contains the property value + * and a hmac hash for the property value. + * "_orig_" will be used to validate the form definition on saving. + * @see \TYPO3\CMS\Form\Domain\Configuration\FormDefinitionValidationService::validateFormDefinitionProperties() + * + * @param mixed $value + */ + public function __invoke(string $key, $value): void + { + $formDefinition = $this->converterDto->getFormDefinition(); + + $renderablePathParts = explode('.', $key); + array_pop($renderablePathParts); + + if (count($renderablePathParts) > 1) { + $renderablePath = implode('.', $renderablePathParts); + $currentFormElement = ArrayUtility::getValueByPath($formDefinition, $renderablePath, '.'); + } else { + $currentFormElement = $formDefinition; + } + + $propertyCollectionElements = $currentFormElement['finishers'] ?? $currentFormElement['validators'] ?? []; + $propertyCollectionName = $currentFormElement['type'] === 'Form' ? 'finishers' : 'validators'; + unset($currentFormElement['renderables'], $currentFormElement['finishers'], $currentFormElement['validators']); + + $this->converterDto + ->setRenderablePathParts($renderablePathParts) + ->setFormElementIdentifier($value); + + GeneralUtility::makeInstance(ArrayProcessor::class, $currentFormElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'addHmacData', + '^.*', + GeneralUtility::makeInstance( + AddHmacDataToFormElementPropertyConverter::class, + $this->converterDto, + $this->sessionToken + ) + ) + ); + + $this->converterDto->setPropertyCollectionName($propertyCollectionName); + foreach ($propertyCollectionElements as $propertyCollectionIndex => $propertyCollectionElement) { + $this->converterDto + ->setPropertyCollectionIndex((int)$propertyCollectionIndex) + ->setPropertyCollectionElementIdentifier($propertyCollectionElement['identifier']); + + GeneralUtility::makeInstance(ArrayProcessor::class, $propertyCollectionElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'addHmacData', + '^(?!(.*\._label|.*\._value)$).*', + GeneralUtility::makeInstance( + AddHmacDataToPropertyCollectionElementConverter::class, + $this->converterDto, + $this->sessionToken + ) + ) + ); + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToFormElementPropertyConverter.php b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToFormElementPropertyConverter.php new file mode 100644 index 0000000..ee65908 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToFormElementPropertyConverter.php @@ -0,0 +1,51 @@ +converterDto->getFormDefinition(); + + $propertyPathParts = explode('.', $key); + $lastKeySegment = array_pop($propertyPathParts); + $propertyPathParts[] = '_orig_' . $lastKeySegment; + + $hashService = GeneralUtility::makeInstance(HashService::class); + $hmacValuePath = implode('.', array_merge($this->converterDto->getRenderablePathParts(), $propertyPathParts)); + $hmacValue = [ + 'value' => $value, + 'hmac' => $hashService->hmac(serialize([$this->converterDto->getFormElementIdentifier(), $key, $value]), $this->sessionToken), + ]; + + $formDefinition = ArrayUtility::setValueByPath($formDefinition, $hmacValuePath, $hmacValue, '.'); + + $this->converterDto->setFormDefinition($formDefinition); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToPropertyCollectionElementConverter.php b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToPropertyCollectionElementConverter.php new file mode 100644 index 0000000..d1870ad --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/AddHmacDataToPropertyCollectionElementConverter.php @@ -0,0 +1,65 @@ +converterDto->getFormDefinition(); + + $propertyPathParts = explode('.', $key); + $lastKeySegment = array_pop($propertyPathParts); + $propertyPathParts[] = '_orig_' . $lastKeySegment; + + $hmacValuePath = implode('.', array_merge( + $this->converterDto->getRenderablePathParts(), + [$this->converterDto->getPropertyCollectionName(), $this->converterDto->getPropertyCollectionIndex()], + $propertyPathParts + )); + + $hashService = GeneralUtility::makeInstance(HashService::class); + $hmacValue = [ + 'value' => $value, + 'hmac' => $hashService->hmac( + serialize([ + $this->converterDto->getFormElementIdentifier(), + $this->converterDto->getPropertyCollectionName(), + $this->converterDto->getPropertyCollectionElementIdentifier(), + $key, + $value, + ]), + $this->sessionToken + ), + ]; + + $formDefinition = ArrayUtility::setValueByPath($formDefinition, $hmacValuePath, $hmacValue, '.'); + + $this->converterDto->setFormDefinition($formDefinition); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/ConverterDto.php b/Classes/Domain/Configuration/FormDefinition/Converters/ConverterDto.php new file mode 100644 index 0000000..fbacc68 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/ConverterDto.php @@ -0,0 +1,125 @@ +formDefinition = $formDefinition; + } + + public function getFormDefinition(): array + { + return $this->formDefinition; + } + + public function setFormDefinition(array $formDefinition): ConverterDto + { + $this->formDefinition = $formDefinition; + return $this; + } + + public function getRenderablePathParts(): array + { + return $this->renderablePathParts; + } + + public function setRenderablePathParts(array $renderablePathParts): ConverterDto + { + $this->renderablePathParts = $renderablePathParts; + return $this; + } + + public function getFormElementIdentifier(): string + { + return $this->formElementIdentifier; + } + + public function setFormElementIdentifier(string $formElementIdentifier): ConverterDto + { + $this->formElementIdentifier = $formElementIdentifier; + return $this; + } + + public function getPropertyCollectionIndex(): int + { + return $this->propertyCollectionIndex; + } + + public function setPropertyCollectionIndex(int $propertyCollectionIndex): ConverterDto + { + $this->propertyCollectionIndex = $propertyCollectionIndex; + return $this; + } + + public function getPropertyCollectionName(): string + { + return $this->propertyCollectionName; + } + + public function setPropertyCollectionName(string $propertyCollectionName): ConverterDto + { + $this->propertyCollectionName = $propertyCollectionName; + return $this; + } + + public function getPropertyCollectionElementIdentifier(): string + { + return $this->propertyCollectionElementIdentifier; + } + + public function setPropertyCollectionElementIdentifier(string $propertyCollectionElementIdentifier): ConverterDto + { + $this->propertyCollectionElementIdentifier = $propertyCollectionElementIdentifier; + return $this; + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/ConverterInterface.php b/Classes/Domain/Configuration/FormDefinition/Converters/ConverterInterface.php new file mode 100644 index 0000000..4c20846 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/ConverterInterface.php @@ -0,0 +1,31 @@ +converterDto = $converterDto; + } + + /** + * Used for overriding finisher options with flexform settings + * Flexform settings "win": When a setting is set in the form + * definition and in flexform the one in flexform will overwrite the + * one defined in the form definition. + * + * Here we adjust the parsed configuration and apply the overrides. + * + * @param string $_ unused in this context + * @param mixed $__ unused in this context + * @param array $matches the expression matches from the ArrayProcessor - for example matches of ^(.*)\.config\.type$ + */ + public function __invoke(string $_, $__, array $matches): void + { + [, $optionKey] = $matches; + $prototypeFinisherDefinition = $this->converterDto->getPrototypeFinisherDefinition(); + $finisherDefinition = $this->converterDto->getFinisherDefinition(); + $finisherIdentifier = $this->converterDto->getFinisherIdentifier(); + $flexFormSheetSettings = $this->converterDto->getFlexFormSheetSettings(); + + try { + $value = ArrayUtility::getValueByPath( + $flexFormSheetSettings['finishers'][$finisherIdentifier], + $optionKey, + '.' + ); + } catch (MissingArrayPathException $exception) { + return; + } + + $fieldConfiguration = $prototypeFinisherDefinition['FormEngine']['elements'][$optionKey] ?? []; + + if ($fieldConfiguration['section'] ?? false) { + if (!is_array($value) || $value === []) { + // Do not process empty values for sections + return; + } + + $processedOptionValue = []; + + foreach ($value as $optionListValue) { + $key = $optionListValue[$fieldConfiguration['sectionItemKey']]; + $value = $optionListValue[$fieldConfiguration['sectionItemValue']]; + $processedOptionValue[$key] = $value; + } + + $value = $processedOptionValue; + } + + $optionPath = 'options.' . $optionKey; + + // Skip additional translation for finisher options that were changed via flexform + if ($this->optionValueHasChanged($finisherDefinition, $optionPath, $value)) { + $finisherDefinition['options']['translation']['propertiesExcludedFromTranslation'][] = $optionKey; + } + + $finisherDefinition = ArrayUtility::setValueByPath($finisherDefinition, $optionPath, $value, '.'); + + $this->converterDto->setFinisherDefinition($finisherDefinition); + } + + /** + * Test if finisher option value differs from finisher definition. + * + * Compares the given finisher option value with the corresponding value in the + * finisher definition. Returns `true` if both values are equal, `false` otherwise. + * + * @param array $finisherDefinition + */ + protected function optionValueHasChanged(array $finisherDefinition, string $optionPath, mixed $value): bool + { + try { + return $value !== ArrayUtility::getValueByPath($finisherDefinition, $optionPath, '.'); + } catch (MissingArrayPathException) { + return true; + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/FinisherTranslationLanguageConverter.php b/Classes/Domain/Configuration/FormDefinition/Converters/FinisherTranslationLanguageConverter.php new file mode 100644 index 0000000..ec18535 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/FinisherTranslationLanguageConverter.php @@ -0,0 +1,54 @@ +converterDto->getFormDefinition(); + + $formDefinition = ArrayUtility::setValueByPath($formDefinition, $key, 'default', '.'); + + $hmacPropertyPathParts = explode('.', $key); + $lastKeySegment = array_pop($hmacPropertyPathParts); + $hmacPropertyPathParts[] = '_orig_' . $lastKeySegment; + $hmacValuePath = implode('.', $hmacPropertyPathParts); + + if (ArrayUtility::isValidPath($formDefinition, $hmacValuePath, '.')) { + $formDefinition = ArrayUtility::removeByPath($formDefinition, $hmacValuePath, '.'); + } + + $this->converterDto->setFormDefinition($formDefinition); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/FlexFormFinisherOverridesConverterDto.php b/Classes/Domain/Configuration/FormDefinition/Converters/FlexFormFinisherOverridesConverterDto.php new file mode 100644 index 0000000..8030fde --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/FlexFormFinisherOverridesConverterDto.php @@ -0,0 +1,83 @@ +prototypeFinisherDefinition = $prototypeFinisherDefinition; + $this->finisherDefinition = $finisherDefinition; + $this->finisherIdentifier = $finisherIdentifier; + $this->flexFormSheetSettings = $flexFormSheetSettings; + } + + public function getPrototypeFinisherDefinition(): array + { + return $this->prototypeFinisherDefinition; + } + + public function getFinisherDefinition(): array + { + return $this->finisherDefinition; + } + + public function setFinisherDefinition(array $finisherDefinition): FlexFormFinisherOverridesConverterDto + { + $this->finisherDefinition = $finisherDefinition; + + return $this; + } + + public function getFinisherIdentifier(): string + { + return $this->finisherIdentifier; + } + + public function getFlexFormSheetSettings(): array + { + return $this->flexFormSheetSettings; + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Converters/RemoveHmacDataConverter.php b/Classes/Domain/Configuration/FormDefinition/Converters/RemoveHmacDataConverter.php new file mode 100644 index 0000000..b8a5d15 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Converters/RemoveHmacDataConverter.php @@ -0,0 +1,43 @@ +") for the corresponding property. + * + * @param mixed $value + */ + public function __invoke(string $key, $value): void + { + $formDefinition = $this->converterDto->getFormDefinition(); + + $propertyPathParts = explode('.', $key); + array_pop($propertyPathParts); + $propertyPath = implode('.', $propertyPathParts); + $formDefinition = ArrayUtility::removeByPath($formDefinition, $propertyPath, '.'); + + $this->converterDto->setFormDefinition($formDefinition); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/AbstractValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/AbstractValidator.php new file mode 100644 index 0000000..da59810 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/AbstractValidator.php @@ -0,0 +1,72 @@ +currentElement = $currentElement; + $this->sessionToken = $sessionToken; + $this->validationDto = $validationDto; + } + + /** + * Builds the path in which the hmac value is expected based on the property path. + */ + protected function buildHmacDataPath(string $propertyPath): string + { + $pathParts = explode('.', $propertyPath); + $lastPathSegment = array_pop($pathParts); + $pathParts[] = '_orig_' . $lastPathSegment; + + return implode('.', $pathParts); + } + + protected function getFormDefinitionValidationService(): FormDefinitionValidationService + { + return GeneralUtility::makeInstance(FormDefinitionValidationService::class); + } + + protected function getConfigurationService(): ConfigurationService + { + return GeneralUtility::makeInstance(ConfigurationService::class); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/CollectionBasedValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/CollectionBasedValidator.php new file mode 100644 index 0000000..fd133da --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/CollectionBasedValidator.php @@ -0,0 +1,82 @@ +buildHmacDataPath($dto->getPropertyPath()); + if (ArrayUtility::isValidPath($currentElement, $hmacDataPath, '.')) { + $hmacData = ArrayUtility::getValueByPath($currentElement, $hmacDataPath, '.'); + + $hmacContent = [ + $dto->getFormElementIdentifier(), + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier(), + $dto->getPropertyPath(), + ]; + + if (!$this->getFormDefinitionValidationService()->isPropertyValueEqualToHistoricalValue($hmacContent, $value, $hmacData, $sessionToken)) { + $message = 'The value "%s" of property "%s" (form element "%s" / "%s.%s") is not equal to the historical value "%s" #1528591586'; + throw new PropertyException( + sprintf( + $message, + $value, + $dto->getPropertyPath(), + $dto->getFormElementIdentifier(), + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier(), + $hmacData['value'] ?? '' + ), + 1528591586 + ); + } + } else { + $message = 'No hmac found for property "%s" (form element "%s" / "%s.%s") #1528591585'; + throw new PropertyException( + sprintf( + $message, + $dto->getPropertyPath(), + $dto->getFormElementIdentifier(), + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier() + ), + 1528591585 + ); + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/CreatableFormElementPropertiesValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/CreatableFormElementPropertiesValidator.php new file mode 100644 index 0000000..03abb1b --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/CreatableFormElementPropertiesValidator.php @@ -0,0 +1,170 @@ +validationDto->withPropertyPath($key); + + if ($this->getConfigurationService()->isFormElementPropertyDefinedInFormEditorSetup($dto)) { + if ($this->getConfigurationService()->formElementPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup($dto)) { + $this->validateFormElementValue($value, $dto); + } + } elseif ( + $this->getConfigurationService()->isFormElementPropertyDefinedInPredefinedDefaultsInFormEditorSetup($dto) + && !ArrayUtility::isValidPath($this->currentElement, $this->buildHmacDataPath($dto->getPropertyPath()), '.') + ) { + $this->validateFormElementPredefinedDefaultValue($value, $dto); + } else { + $this->validateFormElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } + } + + /** + * Throws an exception if the value from a form element property + * does not match the default value from the form editor setup. + * + * @param mixed $value + * @throws PropertyException + */ + protected function validateFormElementPredefinedDefaultValue( + $value, + ValidationDto $dto + ): void { + // If the form element is newly created, we have to compare the $value (form definition) with $predefinedDefaultValue (form setup) + // to check the integrity (at this time we don't have a hmac for the $value to check the integrity) + $predefinedDefaultValue = $this->getConfigurationService()->getFormElementPredefinedDefaultValueFromFormEditorSetup($dto); + if ($value !== $predefinedDefaultValue) { + $throwException = true; + + if (is_string($predefinedDefaultValue)) { + // Last chance: + // Get all translations (from all backend languages) for the untranslated! $predefinedDefaultValue and + // compare the (already translated) $value (from the form definition) against the possible + // translations from $predefinedDefaultValue. + // Usecase: + // * backend language is EN + // * open the form editor and add a ContentElement form element + // * switch to another browser tab and change the backend language to DE + // * clear the cache + // * go back to the form editor and click the save button + // Out of scope: + // * the same scenario as above + delete the previous chosen backend language within the maintenance tool + $untranslatedPredefinedDefaultValue = $this->getConfigurationService()->getFormElementPredefinedDefaultValueFromFormEditorSetup($dto, false); + $translations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKey( + $untranslatedPredefinedDefaultValue, + $dto->getPrototypeName() + ); + + if (in_array($value, $translations, true)) { + $throwException = false; + } + } + + if ($throwException) { + $message = 'The value "%s" of property "%s" (form element "%s") is not equal to the default value "%s" #1528588035'; + throw new PropertyException( + sprintf( + $message, + $value, + $dto->getPropertyPath(), + $dto->getFormElementIdentifier(), + $predefinedDefaultValue + ), + 1528588035 + ); + } + } + } + + /** + * Throws an exception if the value from a form element property + * does not match the allowed set of values (defined within the form setup). + * + * @param mixed $value + * @throws PropertyException + */ + protected function validateFormElementValue( + $value, + ValidationDto $dto + ): void { + $allowedValues = $this->getConfigurationService()->getAllowedValuesForFormElementPropertyFromFormEditorSetup($dto); + + if (!in_array($value, $allowedValues, true)) { + $untranslatedAllowedValues = $this->getConfigurationService()->getAllowedValuesForFormElementPropertyFromFormEditorSetup($dto, false); + // Compare the $value against the untranslated set of allowed values + if (in_array($value, $untranslatedAllowedValues, true)) { + // All good, $value is within the untranslated set of allowed values + return; + } + // Get all translations (from all backend languages) for the untranslated! $allowedValues and + // compare the (already translated) $value (from the form definition) against all possible + // translations for $untranslatedAllowedValues. + $allPossibleAllowedValuesTranslations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKeys( + $untranslatedAllowedValues, + $dto->getPrototypeName() + ); + + foreach ($allPossibleAllowedValuesTranslations as $translations) { + if (in_array($value, $translations, true)) { + // All good, $value is within the set of translated allowed values + return; + } + } + + // Last chance: + // If $value is not configured within the form setup as an allowed value + // but was written within the form definition by hand (and therefore contains a hmac), + // check if $value is manipulated. + // If $value has no hmac or if the hmac exists but is not valid, + // then $this->validatePropertyCollectionElementPropertyValueByHmacData() will + // throw an exception. + $this->validateFormElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/CreatablePropertyCollectionElementPropertiesValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/CreatablePropertyCollectionElementPropertiesValidator.php new file mode 100644 index 0000000..c200d88 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/CreatablePropertyCollectionElementPropertiesValidator.php @@ -0,0 +1,165 @@ +validationDto->withPropertyPath($key); + + if ($this->getConfigurationService()->isPropertyCollectionPropertyDefinedInFormEditorSetup($dto)) { + if ($this->getConfigurationService()->propertyCollectionPropertyHasLimitedAllowedValuesDefinedWithinFormEditorSetup($dto)) { + $this->validatePropertyCollectionPropertyValue($value, $dto); + } + } elseif ( + $this->getConfigurationService()->isPropertyCollectionPropertyDefinedInPredefinedDefaultsInFormEditorSetup($dto) + && !ArrayUtility::isValidPath($this->currentElement, $this->buildHmacDataPath($dto->getPropertyPath()), '.') + ) { + $this->validatePropertyCollectionElementPredefinedDefaultValue($value, $dto); + } else { + $this->validatePropertyCollectionElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } + } + + /** + * Throws an exception if the value from a property collection property + * does not match the default value from the form editor setup. + * + * @param mixed $value + * @throws PropertyException + */ + protected function validatePropertyCollectionElementPredefinedDefaultValue( + $value, + ValidationDto $dto + ): void { + // If the property collection element is newly created, we have to compare the $value (form definition) with $predefinedDefaultValue (form setup) + // to check the integrity (at this time we don't have a hmac on the value to check the integrity) + $predefinedDefaultValue = $this->getConfigurationService()->getPropertyCollectionPredefinedDefaultValueFromFormEditorSetup($dto); + if ($value !== $predefinedDefaultValue) { + $throwException = true; + + if (is_string($predefinedDefaultValue)) { + // Last chance: + // Get all translations (from all backend languages) for the untranslated! $predefinedDefaultValue and + // compare the (already translated) $value (from the form definition) against the possible + // translations from $predefinedDefaultValue. + $untranslatedPredefinedDefaultValue = $this->getConfigurationService()->getPropertyCollectionPredefinedDefaultValueFromFormEditorSetup($dto, false); + $translations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKey( + $untranslatedPredefinedDefaultValue, + $dto->getPrototypeName() + ); + + if (in_array($value, $translations, true)) { + $throwException = false; + } + } + + if ($throwException) { + $message = 'The value "%s" of property "%s" (form element "%s" / "%s.%s") is not equal to the default value "%s" #1528591502'; + throw new PropertyException( + sprintf( + $message, + $value, + $dto->getPropertyPath(), + $dto->getFormElementIdentifier(), + $dto->getPropertyCollectionName(), + $dto->getPropertyCollectionElementIdentifier(), + $predefinedDefaultValue + ), + 1528591502 + ); + } + } + } + + /** + * Throws an exception if the value from a property collection property + * does not match the allowed set of values (defined within the form setup). + * + * @param mixed $value + * @throws PropertyException + */ + protected function validatePropertyCollectionPropertyValue( + $value, + ValidationDto $dto + ): void { + $allowedValues = $this->getConfigurationService()->getAllowedValuesForPropertyCollectionPropertyFromFormEditorSetup($dto); + + if (!in_array($value, $allowedValues, true)) { + $untranslatedAllowedValues = $this->getConfigurationService()->getAllowedValuesForPropertyCollectionPropertyFromFormEditorSetup($dto, false); + // Compare the $value against the untranslated set of allowed values + if (in_array($value, $untranslatedAllowedValues, true)) { + // All good, $value is within the untranslated set of allowed values + return; + } + // Get all translations (from all backend languages) for the untranslated! $allowedValues and + // compare the (already translated) $value (from the form definition) against all possible + // translations for $untranslatedAllowedValues. + $allPossibleAllowedValuesTranslations = $this->getConfigurationService()->getAllBackendTranslationsForTranslationKeys( + $untranslatedAllowedValues, + $dto->getPrototypeName() + ); + + foreach ($allPossibleAllowedValuesTranslations as $translations) { + if (in_array($value, $translations, true)) { + // All good, $value is within the set of translated allowed values + return; + } + } + + // Last chance: + // If $value is not configured within the form setup as an allowed value + // but was written within the form definition by hand (and therefore contains a hmac), + // check if $value is manipulated. + // If $value has no hmac or if the hmac exists but is not valid, + // then $this->validatePropertyCollectionElementPropertyValueByHmacData() will + // throw an exception. + $this->validatePropertyCollectionElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/ElementBasedValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/ElementBasedValidator.php new file mode 100644 index 0000000..d7e1e1a --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/ElementBasedValidator.php @@ -0,0 +1,68 @@ +buildHmacDataPath($dto->getPropertyPath()); + if (ArrayUtility::isValidPath($currentElement, $hmacDataPath, '.')) { + $hmacData = ArrayUtility::getValueByPath($currentElement, $hmacDataPath, '.'); + + $hmacContent = [$dto->getFormElementIdentifier(), $dto->getPropertyPath()]; + if (!$this->getFormDefinitionValidationService()->isPropertyValueEqualToHistoricalValue($hmacContent, $value, $hmacData, $sessionToken)) { + $message = 'The value "%s" of property "%s" (form element "%s") is not equal to the historical value "%s" #1528588036'; + throw new PropertyException( + sprintf( + $message, + $value, + $dto->getPropertyPath(), + $dto->getFormElementIdentifier(), + $hmacData['value'] ?? '' + ), + 1528588036 + ); + } + } else { + $message = 'No hmac found for property "%s" (form element "%s") #1528588037'; + throw new PropertyException( + sprintf($message, $dto->getPropertyPath(), $dto->getFormElementIdentifier()), + 1528588037 + ); + } + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/FormElementHmacDataValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/FormElementHmacDataValidator.php new file mode 100644 index 0000000..22e741f --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/FormElementHmacDataValidator.php @@ -0,0 +1,40 @@ +validationDto->withPropertyPath($key); + $this->validateFormElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/PropertyCollectionElementHmacDataValidator.php b/Classes/Domain/Configuration/FormDefinition/Validators/PropertyCollectionElementHmacDataValidator.php new file mode 100644 index 0000000..ee6ed5e --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/PropertyCollectionElementHmacDataValidator.php @@ -0,0 +1,42 @@ +validationDto->withPropertyPath($key)->withPropertyCollectionElementIdentifier( + $this->currentElement['identifier'] + ); + $this->validatePropertyCollectionElementPropertyValueByHmacData( + $this->currentElement, + $value, + $this->sessionToken, + $dto + ); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/ValidationDto.php b/Classes/Domain/Configuration/FormDefinition/Validators/ValidationDto.php new file mode 100644 index 0000000..6a17a64 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/ValidationDto.php @@ -0,0 +1,159 @@ +prototypeName = $prototypeName; + $this->formElementType = $formElementType; + $this->formElementIdentifier = $formElementIdentifier; + $this->propertyPath = $propertyPath; + $this->propertyCollectionName = $propertyCollectionName; + $this->propertyCollectionElementIdentifier = $propertyCollectionElementIdentifier; + } + + public function getPrototypeName(): string + { + return $this->prototypeName; + } + + public function getFormElementType(): string + { + return $this->formElementType; + } + + public function getFormElementIdentifier(): string + { + return $this->formElementIdentifier; + } + + public function getPropertyPath(): string + { + return $this->propertyPath; + } + + public function getPropertyCollectionName(): string + { + return $this->propertyCollectionName; + } + + public function getPropertyCollectionElementIdentifier(): string + { + return $this->propertyCollectionElementIdentifier; + } + + public function hasPrototypeName(): bool + { + return !empty($this->prototypeName); + } + + public function hasFormElementType(): bool + { + return !empty($this->formElementType); + } + + public function hasFormElementIdentifier(): bool + { + return !empty($this->formElementIdentifier); + } + + public function hasPropertyPath(): bool + { + return !empty($this->propertyPath); + } + + public function hasPropertyCollectionName(): bool + { + return !empty($this->propertyCollectionName); + } + + public function hasPropertyCollectionElementIdentifier(): bool + { + return !empty($this->propertyCollectionElementIdentifier); + } + + public function withPrototypeName(string $prototypeName): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $prototypeName, $this->formElementType, $this->formElementIdentifier, $this->propertyPath, $this->propertyCollectionName, $this->propertyCollectionElementIdentifier); + } + + public function withFormElementType(string $formElementType): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $this->prototypeName, $formElementType, $this->formElementIdentifier, $this->propertyPath, $this->propertyCollectionName, $this->propertyCollectionElementIdentifier); + } + + public function withFormElementIdentifier(string $formElementIdentifier): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $this->prototypeName, $this->formElementType, $formElementIdentifier, $this->propertyPath, $this->propertyCollectionName, $this->propertyCollectionElementIdentifier); + } + + public function withPropertyPath(string $propertyPath): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $this->prototypeName, $this->formElementType, $this->formElementIdentifier, $propertyPath, $this->propertyCollectionName, $this->propertyCollectionElementIdentifier); + } + + public function withPropertyCollectionName(string $propertyCollectionName): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $this->prototypeName, $this->formElementType, $this->formElementIdentifier, $this->propertyPath, $propertyCollectionName, $this->propertyCollectionElementIdentifier); + } + + public function withPropertyCollectionElementIdentifier(string $propertyCollectionElementIdentifier): ValidationDto + { + return GeneralUtility::makeInstance(self::class, $this->prototypeName, $this->formElementType, $this->formElementIdentifier, $this->propertyPath, $this->propertyCollectionName, $propertyCollectionElementIdentifier); + } +} diff --git a/Classes/Domain/Configuration/FormDefinition/Validators/ValidatorInterface.php b/Classes/Domain/Configuration/FormDefinition/Validators/ValidatorInterface.php new file mode 100644 index 0000000..29861f6 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinition/Validators/ValidatorInterface.php @@ -0,0 +1,31 @@ +" for each scalar property value + * within the form definition as a sibling of the property key. + * "_orig_" is an array which contains the property value + * and a hmac hash for the property value. + * "_orig_" will be used to validate the form definition on saving. + * @see \TYPO3\CMS\Form\Domain\Configuration\FormDefinitionValidationService::validateFormDefinitionProperties() + */ + public function addHmacData(array $formDefinition, string $formPersistenceIdentifier): array + { + // Extend the hmac hashing key with a "per form editor session" unique key. + $sessionToken = $this->generateSessionToken(); + $this->persistSessionToken($sessionToken, $formPersistenceIdentifier); + + $converterDto = GeneralUtility::makeInstance(ConverterDto::class, $formDefinition); + + GeneralUtility::makeInstance(ArrayProcessor::class, $formDefinition)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'addHmacData', + '(^identifier$|renderables\.([\d]+)\.identifier$)', + GeneralUtility::makeInstance( + AddHmacDataConverter::class, + $converterDto, + $sessionToken + ) + ) + ); + + $result = $converterDto->getFormDefinition(); + + // Embed the form persistence identifier so the TypeConverter can + // look up the correct per-form session token when saving. + $result['_formPersistenceIdentifier'] = $formPersistenceIdentifier; + + return $result; + } + + /** + * Remove the "_orig_" values and the + * "_formPersistenceIdentifier" marker from the form definition. + */ + public function removeHmacData(array $formDefinition): array + { + unset($formDefinition['_formPersistenceIdentifier']); + + $converterDto = GeneralUtility::makeInstance(ConverterDto::class, $formDefinition); + + GeneralUtility::makeInstance(ArrayProcessor::class, $formDefinition)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'removeHmacData', + '(_orig_.*|.*\._orig_.*)\.hmac', + GeneralUtility::makeInstance( + RemoveHmacDataConverter::class, + $converterDto + ) + ) + ); + + return $converterDto->getFormDefinition(); + } + + /** + * Migrate various finisher options + */ + public function migrateFinisherConfiguration(array $formDefinition): array + { + $converterDto = GeneralUtility::makeInstance(ConverterDto::class, $formDefinition); + + GeneralUtility::makeInstance(ArrayProcessor::class, $formDefinition)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'migrateFinisherLanguageSettings', + '^finishers\.([\d]+)\.options.translation.language$', + GeneralUtility::makeInstance( + FinisherTranslationLanguageConverter::class, + $converterDto + ) + ) + ); + + return $converterDto->getFormDefinition(); + } + + protected function persistSessionToken(string $sessionToken, string $formPersistenceIdentifier): void + { + $tokens = $this->getBackendUser()->getSessionData('extFormProtectionSessionTokens') ?? []; + if (!is_array($tokens)) { + $tokens = []; + } + $tokens[$formPersistenceIdentifier] = $sessionToken; + $this->getBackendUser()->setAndSaveSessionData('extFormProtectionSessionTokens', $tokens); + } + + /** + * Retrieve the session token for a specific form persistence identifier. + */ + public function retrieveSessionToken(string $formPersistenceIdentifier): string + { + $tokens = $this->getBackendUser()->getSessionData('extFormProtectionSessionTokens'); + if (is_array($tokens) && isset($tokens[$formPersistenceIdentifier]) && is_string($tokens[$formPersistenceIdentifier])) { + return $tokens[$formPersistenceIdentifier]; + } + return ''; + } + + public function sanitizeHtml(array $rawFormDefinitionArray, array $rtePropertyPaths = [], string $defaultBuild = 'default'): array + { + return $this->sanitizeValuesRecursively($rawFormDefinitionArray, $rtePropertyPaths, $defaultBuild); + } + + public function transformRteContentForPersistence(array $formDefinition, array $rtePropertyPaths): array + { + if ($rtePropertyPaths === []) { + return $formDefinition; + } + + return $this->transformRteContentRecursively($formDefinition, $rtePropertyPaths, $this->richTextConfigurationService, 'persistence'); + } + + public function transformRteContentForRichTextEditor(array $formDefinition, array $rtePropertyPaths): array + { + if ($rtePropertyPaths === []) { + return $formDefinition; + } + + return $this->transformRteContentRecursively($formDefinition, $rtePropertyPaths, $this->richTextConfigurationService, 'rte'); + } + + protected function transformRteContentRecursively( + array $formDefinition, + array $rtePropertyPaths, + RichTextConfigurationService $richTextConfigurationService, + string $direction = 'persistence' + ): array { + // Get the element type (e.g., 'Checkbox', 'StaticText', 'Form') + $elementType = $formDefinition['type'] ?? null; + + // Transform properties for this specific element type + if ($elementType !== null && isset($rtePropertyPaths[$elementType])) { + foreach ($rtePropertyPaths[$elementType] as $propertyPath => $presetName) { + $value = $this->getValueByPath($formDefinition, $propertyPath); + if (is_string($value) && $value !== '') { + $transformedValue = $direction === 'persistence' + ? $richTextConfigurationService->transformTextForPersistence($value, $presetName) + : $richTextConfigurationService->transformTextForRichTextEditor($value, $presetName); + $formDefinition = $this->setValueByPath($formDefinition, $propertyPath, $transformedValue); + } + } + } + + // Recurse into renderables (form elements on pages) + if (is_array($formDefinition['renderables'] ?? null)) { + foreach ($formDefinition['renderables'] as $key => $renderable) { + if (is_array($renderable)) { + $formDefinition['renderables'][$key] = $this->transformRteContentRecursively( + $renderable, + $rtePropertyPaths, + $richTextConfigurationService, + $direction + ); + } + } + } + + // Transform finisher options + if (is_array($formDefinition['finishers'] ?? null)) { + $finisherRtePaths = $rtePropertyPaths['_finishers'] ?? []; + foreach ($formDefinition['finishers'] as $key => $finisher) { + if (!is_array($finisher)) { + continue; + } + + $finisherIdentifier = $finisher['identifier'] ?? null; + if ($finisherIdentifier === null || !isset($finisherRtePaths[$finisherIdentifier])) { + continue; + } + + foreach ($finisherRtePaths[$finisherIdentifier] as $propertyPath => $presetName) { + // Property path in finisher config is like 'options.message' + $value = $this->getValueByPath($finisher, $propertyPath); + if (is_string($value) && $value !== '') { + $transformedValue = $direction === 'persistence' + ? $richTextConfigurationService->transformTextForPersistence($value, $presetName) + : $richTextConfigurationService->transformTextForRichTextEditor($value, $presetName); + $finisher = $this->setValueByPath($finisher, $propertyPath, $transformedValue); + $formDefinition['finishers'][$key] = $finisher; + } + } + } + } + + return $formDefinition; + } + + protected function getValueByPath(array $array, string $path): mixed + { + $keys = explode('.', $path); + $current = $array; + + foreach ($keys as $key) { + if (!is_array($current) || !array_key_exists($key, $current)) { + return null; + } + $current = $current[$key]; + } + + return $current; + } + + protected function setValueByPath(array $array, string $path, mixed $value): array + { + $keys = explode('.', $path); + $current = &$array; + + foreach ($keys as $i => $key) { + if ($i === count($keys) - 1) { + $current[$key] = $value; + } else { + if (!isset($current[$key]) || !is_array($current[$key])) { + $current[$key] = []; + } + $current = &$current[$key]; + } + } + + return $array; + } + + /** + * Extract RTE-enabled property paths from prototype configuration. + * + * Scans the form editor configuration for all form element types and finishers + * to find editors with enableRichtext=true and returns their property paths + * along with the RTE preset name, organized by element type. + * + * @param array $prototypeConfiguration The prototype configuration array + * @return array Map of element types to their RTE property paths + * Format: [ + * 'Checkbox' => ['label' => 'form-label'], + * 'StaticText' => ['properties.text' => 'form-content'], + * '_finishers' => ['Confirmation' => ['options.message' => 'form-label']] + * ] + */ + public function extractRtePropertyPaths(array $prototypeConfiguration): array + { + $rtePropertyPaths = []; + + // Extract from form elements definition + $formElementsDefinition = $prototypeConfiguration['formElementsDefinition'] ?? []; + foreach ($formElementsDefinition as $formElementType => $elementConfig) { + $editors = $elementConfig['formEditor']['editors'] ?? []; + foreach ($editors as $editor) { + if ($this->isRteEditor($editor)) { + $propertyPath = $editor['propertyPath'] ?? ''; + $presetName = $editor['richtextConfiguration'] ?? 'form-label'; + if ($propertyPath !== '') { + $rtePropertyPaths[$formElementType][$propertyPath] = $presetName; + } + } + } + } + + // Extract from finisher property collections on the Form element + // Finisher editors are defined in: + // formElementsDefinition.Form.formEditor.propertyCollections.finishers..editors + $finisherCollections = $formElementsDefinition['Form']['formEditor']['propertyCollections']['finishers'] ?? []; + foreach ($finisherCollections as $finisherCollection) { + $finisherIdentifier = $finisherCollection['identifier'] ?? ''; + if ($finisherIdentifier === '') { + continue; + } + $editors = $finisherCollection['editors'] ?? []; + foreach ($editors as $editor) { + if ($this->isRteEditor($editor)) { + $propertyPath = $editor['propertyPath'] ?? ''; + $presetName = $editor['richtextConfiguration'] ?? 'form-label'; + if ($propertyPath !== '') { + $rtePropertyPaths['_finishers'][$finisherIdentifier][$propertyPath] = $presetName; + } + } + } + } + + return $rtePropertyPaths; + } + + /** + * Check if an editor configuration represents an RTE-enabled textarea. + */ + protected function isRteEditor(array $editor): bool + { + return ($editor['templateName'] ?? '') === 'Inspector-TextareaEditor' + && ($editor['enableRichtext'] ?? false) === true; + } + + /** + * Recursively sanitizes values in form definition. + * + * For RTE-enabled fields: Uses HtmlSanitizer with the preset configured in the RTE configuration + * For all other string fields: Uses strip_tags to remove ALL HTML + * + * @param array $array The array to sanitize + * @param array $rtePropertyPaths Map of element types to their RTE property paths with preset names + * @param string $defaultBuild Default sanitizer build name for RTE fields without specific preset + * @param string|null $currentElementType The current element type being processed + * @param string $currentPath The current property path being processed + */ + protected function sanitizeValuesRecursively( + array $array, + array $rtePropertyPaths = [], + string $defaultBuild = 'default', + ?string $currentElementType = null, + string $currentPath = '' + ): array { + $result = $array; + + // Detect element type from current array (only at element root level) + $elementType = $result['type'] ?? $currentElementType; + + // Get RTE property paths for this element type (with their preset names) + $elementRtePaths = []; + if ($elementType !== null && isset($rtePropertyPaths[$elementType])) { + $elementRtePaths = $rtePropertyPaths[$elementType]; + } + + foreach ($result as $key => $value) { + // Build the full property path + $propertyPath = $currentPath === '' ? $key : $currentPath . '.' . $key; + + if ($key === 'renderables' && is_array($value)) { + // For renderables, process each child element with fresh context + foreach ($value as $childKey => $childValue) { + if (is_array($childValue)) { + $result[$key][$childKey] = $this->sanitizeValuesRecursively( + $childValue, + $rtePropertyPaths, + $defaultBuild + ); + } + } + } elseif ($key === 'finishers' && is_array($value)) { + // Handle finishers separately + $finisherRtePaths = $rtePropertyPaths['_finishers'] ?? []; + foreach ($value as $finisherKey => $finisher) { + if (is_array($finisher)) { + $finisherIdentifier = $finisher['identifier'] ?? null; + $finisherRteFields = []; + if ($finisherIdentifier !== null && isset($finisherRtePaths[$finisherIdentifier])) { + $finisherRteFields = $finisherRtePaths[$finisherIdentifier]; + } + $result[$key][$finisherKey] = $this->sanitizeFinisherRecursively( + $finisher, + $finisherRteFields, + $defaultBuild + ); + } + } + } elseif (is_array($value)) { + // Recurse into nested arrays, keeping the element type and building path + $result[$key] = $this->sanitizeValuesRecursively( + $value, + $rtePropertyPaths, + $defaultBuild, + $elementType, + $propertyPath + ); + } elseif (is_string($value) || (is_object($value) && method_exists($value, '__toString'))) { + $stringValue = (string)$value; + + // Check if this property path is an RTE field for the current element type + if (isset($elementRtePaths[$propertyPath])) { + // RTE field: use HtmlSanitizer with the configured preset + // This ensures sanitization even for form definitions from external sources + $presetBuild = $this->resolveSanitizerBuildFromPreset($elementRtePaths[$propertyPath]); + $result[$key] = $this->sanitizeWithBuild($stringValue, $presetBuild ?? $defaultBuild); + } else { + // Non-RTE field: strip ALL HTML tags for security + $result[$key] = strip_tags($stringValue); + } + } + } + + return $result; + } + + /** + * Recursively sanitize finisher values. + * + * @param array $finisher The finisher configuration + * @param array $rteFields Map of RTE field paths to their preset names + * @param string $defaultBuild Default sanitizer build name + * @param string $currentPath Current property path + */ + protected function sanitizeFinisherRecursively( + array $finisher, + array $rteFields, + string $defaultBuild = 'default', + string $currentPath = '' + ): array { + foreach ($finisher as $key => $value) { + $fullPath = $currentPath === '' ? $key : $currentPath . '.' . $key; + + if (is_array($value)) { + $finisher[$key] = $this->sanitizeFinisherRecursively($value, $rteFields, $defaultBuild, $fullPath); + } elseif (is_string($value) || (is_object($value) && method_exists($value, '__toString'))) { + $stringValue = (string)$value; + + if (isset($rteFields[$fullPath])) { + // RTE field: use HtmlSanitizer with the configured preset + $presetBuild = $this->resolveSanitizerBuildFromPreset($rteFields[$fullPath]); + $finisher[$key] = $this->sanitizeWithBuild($stringValue, $presetBuild ?? $defaultBuild); + } else { + // Non-RTE field: strip ALL HTML tags for security + $finisher[$key] = strip_tags($stringValue); + } + } + } + + return $finisher; + } + + /** + * Resolve the sanitizer build name from an RTE preset configuration. + * + * @param string $presetName The RTE preset name (e.g., 'form-label', 'form-content') + * @return string|null The sanitizer build name, or null if not configured + */ + protected function resolveSanitizerBuildFromPreset(string $presetName): ?string + { + $processingConfig = $this->richTextConfigurationService->resolveProcessingConfiguration($presetName); + return $processingConfig['HTMLparser_db.']['htmlSanitize.']['build'] ?? null; + } + + /** + * Sanitize HTML content with the specified sanitizer build. + * + * @param string $content The HTML content to sanitize + * @param string $build The sanitizer build name or class name + * @return string The sanitized content + */ + protected function sanitizeWithBuild(string $content, string $build): string + { + return $this->createSanitizer($build)->sanitize($content); + } + + /** + * Create a sanitizer instance for the given build configuration. + * + * Supports both preset names (e.g., 'default') and class names implementing BuilderInterface. + * + * @param string $build The sanitizer build name or class name + * @return Sanitizer The sanitizer instance + */ + protected function createSanitizer(string $build): Sanitizer + { + if (class_exists($build) && is_a($build, \TYPO3\HtmlSanitizer\Builder\BuilderInterface::class, true)) { + $builder = GeneralUtility::makeInstance($build); + } else { + $factory = GeneralUtility::makeInstance(SanitizerBuilderFactory::class); + $builder = $factory->build($build); + } + return $builder->build(); + } + + /** + * Generates the random token which is used in the hash for the form tokens. + * + * @return string + */ + protected function generateSessionToken(): string + { + return GeneralUtility::makeInstance(Random::class)->generateRandomHexString(64); + } + + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } +} diff --git a/Classes/Domain/Configuration/FormDefinitionValidationService.php b/Classes/Domain/Configuration/FormDefinitionValidationService.php new file mode 100644 index 0000000..4901b67 --- /dev/null +++ b/Classes/Domain/Configuration/FormDefinitionValidationService.php @@ -0,0 +1,352 @@ +configurationService->isFormElementTypeCreatableByFormEditor($validationDto)) { + $this->validateAllPropertyValuesFromCreatableFormElement( + $currentFormElement, + $sessionToken, + $validationDto + ); + foreach ($propertyCollectionElements as $propertyCollectionElement) { + $validationDto = $validationDto->withPropertyCollectionElementIdentifier( + $propertyCollectionElement['identifier'] + ); + if ($this->configurationService->isPropertyCollectionElementIdentifierCreatableByFormEditor($validationDto)) { + $this->validateAllPropertyValuesFromCreatablePropertyCollectionElement( + $propertyCollectionElement, + $sessionToken, + $validationDto + ); + } else { + $this->validateAllPropertyCollectionElementValuesByHmac( + $propertyCollectionElement, + $sessionToken, + $validationDto + ); + } + } + } else { + $this->validateAllFormElementPropertyValuesByHmac($currentFormElement, $sessionToken, $validationDto); + foreach ($propertyCollectionElements as $propertyCollectionElement) { + $this->validateAllPropertyCollectionElementValuesByHmac( + $propertyCollectionElement, + $sessionToken, + $validationDto + ); + } + } + + foreach ($renderables as $renderable) { + $this->validateFormDefinitionProperties($renderable, $prototypeName, $sessionToken); + } + } + + /** + * Returns TRUE if a property value is equals to the historical value + * and FALSE if not. + * "Historical values" means values which are available within the form definition + * while the form editor is loaded and the values which are available after a + * successful validation of the form definition on a save operation. + * The value must be equal to the historical value if the property key for the value + * is not defined within the form setup. + * This means that the property can not be changed by the form editor but we want to keep the value + * in its original state. + * If this is not the case (return value is FALSE), an exception must be thrown. + * + * @throws PropertyException + */ + public function isPropertyValueEqualToHistoricalValue( + array $hmacContent, + mixed $propertyValue, + array $hmacData, + string $sessionToken + ): bool { + $this->checkHmacDataIntegrity($hmacData, $hmacContent, $sessionToken); + $hmacContent[] = $propertyValue; + $expectedHash = $this->hashService->hmac(serialize($hmacContent), $sessionToken); + return hash_equals($expectedHash, $hmacData['hmac']); + } + + /** + * Compares the historical value and the hmac hash to ensure the integrity + * of the data. + * An exception will be thrown if the value is modified. + * + * @throws PropertyException + */ + protected function checkHmacDataIntegrity(array $hmacData, array $hmacContent, string $sessionToken) + { + $hmac = $hmacData['hmac'] ?? null; + if (empty($hmac)) { + throw new PropertyException('Hmac must not be empty. #1528538222', 1528538222); + } + $hmacContent[] = $hmacData['value'] ?? ''; + $expectedHash = $this->hashService->hmac(serialize($hmacContent), $sessionToken); + if (!hash_equals($expectedHash, $hmac)) { + throw new PropertyException('Unauthorized modification of historical data. #1528538252', 1528538252); + } + } + + /** + * Walk through all form element properties and checks + * if the values matches to their hmac hashes. + */ + protected function validateAllFormElementPropertyValuesByHmac( + array $currentElement, + string $sessionToken, + ValidationDto $validationDto + ): void { + GeneralUtility::makeInstance(ArrayProcessor::class, $currentElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'validateProperties', + '^(?!(_orig_.*|.*\._orig_.*)$).*', + GeneralUtility::makeInstance( + FormElementHmacDataValidator::class, + $currentElement, + $sessionToken, + $validationDto + ) + ) + ); + } + + /** + * Walk through all property collection properties and checks + * if the values matches to their hmac hashes. + */ + protected function validateAllPropertyCollectionElementValuesByHmac( + array $currentElement, + string $sessionToken, + ValidationDto $validationDto + ): void { + GeneralUtility::makeInstance(ArrayProcessor::class, $currentElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'validateProperties', + '^(?!(_orig_.*|.*\._orig_.*)$).*', + GeneralUtility::makeInstance( + PropertyCollectionElementHmacDataValidator::class, + $currentElement, + $sessionToken, + $validationDto + ) + ) + ); + } + + /** + * Walk through all form element properties and checks + * if the property is defined within the form editor setup + * or if the property is defined within the "predefinedDefaults" in the form editor setup + * and the property value matches the predefined value + * or if there is a valid hmac hash for the value. + */ + protected function validateAllPropertyValuesFromCreatableFormElement( + array $currentElement, + string $sessionToken, + ValidationDto $validationDto + ): void { + GeneralUtility::makeInstance(ArrayProcessor::class, $currentElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'validateProperties', + '^(?!(_orig_.*|.*\._orig_.*|type|identifier)$).*', + GeneralUtility::makeInstance( + CreatableFormElementPropertiesValidator::class, + $currentElement, + $sessionToken, + $validationDto + ) + ) + ); + } + + /** + * Walk through all property collection properties and checks + * if the property is defined within the form editor setup + * or if the property is defined within the "predefinedDefaults" in the form editor setup + * and the property value matches the predefined value + * or if there is a valid hmac hash for the value. + */ + protected function validateAllPropertyValuesFromCreatablePropertyCollectionElement( + array $currentElement, + string $sessionToken, + ValidationDto $validationDto + ): void { + GeneralUtility::makeInstance(ArrayProcessor::class, $currentElement)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'validateProperties', + '^(?!(_orig_.*|.*\._orig_.*|identifier)$).*', + GeneralUtility::makeInstance( + CreatablePropertyCollectionElementPropertiesValidator::class, + $currentElement, + $sessionToken, + $validationDto + ) + ) + ); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AbstractExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AbstractExtractor.php new file mode 100644 index 0000000..724abd7 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AbstractExtractor.php @@ -0,0 +1,34 @@ +extractorDto = $extractorDto; + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AdditionalElementPropertyPathsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AdditionalElementPropertyPathsExtractor.php new file mode 100644 index 0000000..58bbdd5 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/AdditionalElementPropertyPathsExtractor.php @@ -0,0 +1,36 @@ +extractorDto->getResult(); + $result['formElements'][$formElementType]['additionalElementPropertyPaths'][] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorDto.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorDto.php new file mode 100644 index 0000000..68e851e --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorDto.php @@ -0,0 +1,55 @@ +prototypeConfiguration = $prototypeConfiguration; + } + + public function getPrototypeConfiguration(): array + { + return $this->prototypeConfiguration; + } + + public function getResult(): array + { + return $this->result; + } + + public function setResult(array $result): ExtractorDto + { + $this->result = $result; + return $this; + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorInterface.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorInterface.php new file mode 100644 index 0000000..7755b1a --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/ExtractorInterface.php @@ -0,0 +1,31 @@ +extractorDto->getResult(); + + if (!ArrayUtility::isValidPath( + $this->extractorDto->getPrototypeConfiguration(), + 'formElementsDefinition.' . $formElementType . '.formEditor.groupSorting', + '.' + )) { + $result['formElements'][$formElementType]['creatable'] = false; + $this->extractorDto->setResult($result); + return; + } + + $formElementGroups = array_keys( + ArrayUtility::getValueByPath($this->extractorDto->getPrototypeConfiguration(), 'formEditor.formElementGroups', '.') + ); + + $result['formElements'][$formElementType]['creatable'] = in_array( + $formElementGroup, + $formElementGroups, + true + ); + + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/MultiValuePropertiesExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/MultiValuePropertiesExtractor.php new file mode 100644 index 0000000..bb0bb9b --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/MultiValuePropertiesExtractor.php @@ -0,0 +1,89 @@ +extractorDto->getResult(); + + if (ArrayUtility::isValidPath($this->extractorDto->getPrototypeConfiguration(), $propertyPath, '.')) { + $result['formElements'][$formElementType]['multiValueProperties'][] = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + $propertyPath, + '.' + ); + } + + if ($value === 'Inspector-PropertyGridEditor') { + $result['formElements'][$formElementType]['multiValueProperties'][] = 'defaultValue'; + } + + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PredefinedDefaultsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PredefinedDefaultsExtractor.php new file mode 100644 index 0000000..28ad329 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PredefinedDefaultsExtractor.php @@ -0,0 +1,38 @@ +extractorDto->getResult(); + $result['formElements'][$formElementType]['predefinedDefaults'][$propertyPath] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PropertyPathsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PropertyPathsExtractor.php new file mode 100644 index 0000000..920b01c --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/PropertyPathsExtractor.php @@ -0,0 +1,90 @@ +getPropertyPaths($value, $matches); + + $result = $this->extractorDto->getResult(); + $result = array_merge_recursive($result, ['formElements' => $formElementPropertyPaths]); + $this->extractorDto->setResult($result); + } + + protected function getPropertyPaths(string $value, array $matches): array + { + $paths = []; + [, $formElementType, $formEditorIndex] = $matches; + + $paths[$formElementType]['propertyPaths'] = []; + $templateNamePath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'templateName', + ] + ); + $templateName = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + $templateNamePath, + '.' + ); + + // Special processing of "Inspector-GridColumnViewPortConfigurationEditor" inspector editors. + // Expand the property path which contains a "{@viewPortIdentifier}" placeholder + // to X property paths which contain all available placeholder replacements. + if ($templateName === 'Inspector-GridColumnViewPortConfigurationEditor') { + $viewPortsPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'configurationOptions', + 'viewPorts', + ] + ); + $viewPorts = ArrayUtility::getValueByPath($this->extractorDto->getPrototypeConfiguration(), $viewPortsPath, '.'); + foreach ($viewPorts as $viewPort) { + $viewPortIdentifier = $viewPort['viewPortIdentifier']; + $propertyPath = str_replace('{@viewPortIdentifier}', $viewPortIdentifier, $value); + $paths[$formElementType]['propertyPaths'][] = $propertyPath; + } + } else { + $paths[$formElementType]['propertyPaths'][] = $value; + } + return $paths; + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/SelectOptionsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/SelectOptionsExtractor.php new file mode 100644 index 0000000..126d9b8 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/FormElement/SelectOptionsExtractor.php @@ -0,0 +1,95 @@ +extractorDto->getPrototypeConfiguration(), + implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'templateName', + ] + ), + '.' + ); + + if ($templateName === 'Inspector-FinishersEditor') { + $propertyPath = '_finishers'; + } elseif ($templateName === 'Inspector-ValidatorsEditor') { + $propertyPath = '_validators'; + } else { + if ($templateName === 'Inspector-RequiredValidatorEditor') { + $propertyPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'configurationOptions', + 'validationErrorMessage', + 'propertyPath', + ] + ); + } else { + $propertyPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'propertyPath', + ] + ); + } + + $propertyPath = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + $propertyPath, + '.' + ); + } + + $result = $this->extractorDto->getResult(); + $result['formElements'][$formElementType]['selectOptions'][$propertyPath][] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/IsCreatablePropertyCollectionElementExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/IsCreatablePropertyCollectionElementExtractor.php new file mode 100644 index 0000000..4839ece --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/IsCreatablePropertyCollectionElementExtractor.php @@ -0,0 +1,103 @@ +extractorDto->getResult(); + + if ( + $value === 'Inspector-FinishersEditor' + || $value === 'Inspector-ValidatorsEditor' + ) { + $selectOptionsPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'selectOptions', + ] + ); + if (!ArrayUtility::isValidPath($this->extractorDto->getPrototypeConfiguration(), $selectOptionsPath, '.')) { + return; + } + $selectOptions = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + $selectOptionsPath, + '.' + ); + foreach ($selectOptions as $selectOption) { + $validatorIdentifier = $selectOption['value'] ?? ''; + if (empty($validatorIdentifier)) { + continue; + } + + $result['formElements'][$formElementType]['collections'][$propertyCollectionName][$validatorIdentifier]['creatable'] = true; + } + } else { + $validatorIdentifierPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'editors', + $formEditorIndex, + 'validatorIdentifier', + ] + ); + if (!ArrayUtility::isValidPath($this->extractorDto->getPrototypeConfiguration(), $validatorIdentifierPath, '.')) { + return; + } + $validatorIdentifier = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + $validatorIdentifierPath, + '.' + ); + $result['formElements'][$formElementType]['collections'][$propertyCollectionName][$validatorIdentifier]['creatable'] = true; + } + + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/MultiValuePropertiesExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/MultiValuePropertiesExtractor.php new file mode 100644 index 0000000..85cad00 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/MultiValuePropertiesExtractor.php @@ -0,0 +1,90 @@ +extractorDto->getPrototypeConfiguration(), $propertyPath, '.'); + + $result = $this->extractorDto->getResult(); + + if ( + $value === 'Inspector-PropertyGridEditor' + || $value === 'Inspector-MultiSelectEditor' + ) { + $identifierPath = implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'propertyCollections', + $propertyCollectionName, + $propertyCollectionIndex, + 'identifier', + ] + ); + $identifier = ArrayUtility::getValueByPath($this->extractorDto->getPrototypeConfiguration(), $identifierPath, '.'); + + $result['formElements'][$formElementType]['collections'][$propertyCollectionName][$identifier]['multiValueProperties'][] = $propertyValue; + if ($value === 'Inspector-PropertyGridEditor') { + $result['formElements'][$formElementType]['collections'][$propertyCollectionName][$identifier]['multiValueProperties'][] = 'defaultValue'; + } + } else { + $result['formElements'][$formElementType]['multiValueProperties'][] = $propertyValue; + } + + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PredefinedDefaultsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PredefinedDefaultsExtractor.php new file mode 100644 index 0000000..194b5c8 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PredefinedDefaultsExtractor.php @@ -0,0 +1,39 @@ +extractorDto->getResult(); + $result['collections'][$propertyCollectionName][$propertyCollectionElementIdentifier]['predefinedDefaults'][$propertyPath] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PropertyPathsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PropertyPathsExtractor.php new file mode 100644 index 0000000..08e9a84 --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/PropertyPathsExtractor.php @@ -0,0 +1,53 @@ +extractorDto->getPrototypeConfiguration(), $identifierPath, '.'); + + $result = $this->extractorDto->getResult(); + $result['formElements'][$formElementType]['collections'][$propertyCollectionName][$identifier]['propertyPaths'][] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/SelectOptionsExtractor.php b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/SelectOptionsExtractor.php new file mode 100644 index 0000000..352e6bf --- /dev/null +++ b/Classes/Domain/Configuration/FrameworkConfiguration/Extractors/PropertyCollectionElement/SelectOptionsExtractor.php @@ -0,0 +1,77 @@ +extractorDto->getPrototypeConfiguration(), + implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'propertyCollections', + $propertyCollectionName, + $propertyCollectionIndex, + 'editors', + $propertyCollectionEditorIndex, + 'propertyPath', + ] + ), + '.' + ); + + $propertyCollectionElementIdentifier = ArrayUtility::getValueByPath( + $this->extractorDto->getPrototypeConfiguration(), + implode( + '.', + [ + 'formElementsDefinition', + $formElementType, + 'formEditor', + 'propertyCollections', + $propertyCollectionName, + $propertyCollectionIndex, + 'identifier', + ] + ), + '.' + ); + + $propertyCollectionName = str_replace('Definition', '', $propertyCollectionName); + + $result = $this->extractorDto->getResult(); + $result['collections'][$propertyCollectionName][$propertyCollectionElementIdentifier]['selectOptions'][$propertyPath][] = $value; + $this->extractorDto->setResult($result); + } +} diff --git a/Classes/Domain/Configuration/PersistenceConfigurationService.php b/Classes/Domain/Configuration/PersistenceConfigurationService.php new file mode 100644 index 0000000..15d0f69 --- /dev/null +++ b/Classes/Domain/Configuration/PersistenceConfigurationService.php @@ -0,0 +1,155 @@ +isFrontendRequest(); + $request = $this->getCurrentRequest(); + + $typoScriptSettings = $this->extbaseConfigurationManager->getConfiguration( + ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, + 'form' + ); + + return $this->extFormConfigurationManager->getYamlConfiguration( + $typoScriptSettings, + $isFrontend, + $isFrontend ? $request : null + ); + } + + /** + * Get persistence manager settings as a typed DTO + */ + public function getPersistenceManagerConfiguration(): PersistenceManagerConfiguration + { + $formSettings = $this->getFormSettings(); + return PersistenceManagerConfiguration::fromArray($formSettings['persistenceManager'] ?? []); + } + + /** + * Get allowed extension paths from form configuration + * + * @return string[] Array of allowed extension paths (e.g., ["EXT:my_extension/Configuration/Forms/"]) + */ + public function getAllowedExtensionPaths(): array + { + return $this->getPersistenceManagerConfiguration()->allowedExtensionPaths; + } + + /** + * Get allowed pages for form storage. + * + * Forms are always stored on pid 0 (root level). + * + * @return array Array of allowed page IDs + */ + public function getAllowedPages(): array + { + return [ + 0 => [ + 'uid' => 0, + 'title' => 'Root', + ], + ]; + } + + /** + * Check if saving to extension paths is allowed + */ + public function isAllowedToSaveToExtensionPaths(): bool + { + return $this->getPersistenceManagerConfiguration()->allowSaveToExtensionPaths; + } + + /** + * Check if deleting from extension paths is allowed + */ + public function isAllowedToDeleteFromExtensionPaths(): bool + { + return $this->getPersistenceManagerConfiguration()->allowDeleteFromExtensionPaths; + } + + /** + * Get sort configuration for form listing + * + * @return array{sortByKeys: string[], sortAscending: bool} + */ + public function getSortConfiguration(): array + { + $configuration = $this->getPersistenceManagerConfiguration(); + + return [ + 'sortByKeys' => $configuration->sortByKeys, + 'sortAscending' => $configuration->sortAscending, + ]; + } + + /** + * Check if current request is a frontend request + */ + private function isFrontendRequest(): bool + { + $request = $this->getCurrentRequest(); + + if ($request !== null) { + return ApplicationType::fromRequest($request)->isFrontend(); + } + + return false; + } + + /** + * Get current request from globals + */ + private function getCurrentRequest(): ?ServerRequestInterface + { + return $GLOBALS['TYPO3_REQUEST'] ?? null; + } +} diff --git a/Classes/Domain/DTO/FormData.php b/Classes/Domain/DTO/FormData.php new file mode 100644 index 0000000..93fad7b --- /dev/null +++ b/Classes/Domain/DTO/FormData.php @@ -0,0 +1,66 @@ + $this->identifier, + 'type' => $this->type, + 'label' => $this->name, + 'prototypeName' => $this->prototypeName, + 'renderingOptions' => $this->renderingOptions, + 'finishers' => $this->finishers, + 'renderables' => $this->renderables, + 'variants' => $this->variants, + ]; + } +} diff --git a/Classes/Domain/DTO/FormMetadata.php b/Classes/Domain/DTO/FormMetadata.php new file mode 100644 index 0000000..01e8ff4 --- /dev/null +++ b/Classes/Domain/DTO/FormMetadata.php @@ -0,0 +1,208 @@ +withPersistenceIdentifier($persistenceIdentifier) + ->withFileUid($fileUid); + } + + public function toArray(): array + { + return [ + 'identifier' => $this->identifier, + 'type' => $this->type, + 'label' => $this->name, + 'name' => $this->name, + 'prototypeName' => $this->prototypeName, + 'persistenceIdentifier' => $this->persistenceIdentifier ?? $this->identifier, + 'invalid' => $this->invalid, + 'readOnly' => $this->readOnly, + 'removable' => $this->removable, + 'storageType' => $this->storageType, + 'storageLocation' => $this->storageLocation ?? $this->storageType, + 'duplicateIdentifier' => $this->duplicateIdentifier, + 'fileUid' => $this->fileUid, + 'referenceCount' => $this->referenceCount, + 'editUrl' => $this->editUrl, + 'actions' => $this->actions, + ]; + } + + private function with(array $changes): self + { + return new self( + identifier: $changes['identifier'] ?? $this->identifier, + type: $changes['type'] ?? $this->type, + name: $changes['name'] ?? $this->name, + prototypeName: $changes['prototypeName'] ?? $this->prototypeName, + persistenceIdentifier: $changes['persistenceIdentifier'] ?? $this->persistenceIdentifier, + invalid: $changes['invalid'] ?? $this->invalid, + readOnly: $changes['readOnly'] ?? $this->readOnly, + removable: $changes['removable'] ?? $this->removable, + storageType: $changes['storageType'] ?? $this->storageType, + duplicateIdentifier: $changes['duplicateIdentifier'] ?? $this->duplicateIdentifier, + fileUid: $changes['fileUid'] ?? $this->fileUid, + referenceCount: $changes['referenceCount'] ?? $this->referenceCount, + editUrl: $changes['editUrl'] ?? $this->editUrl, + storageLocation: $changes['storageLocation'] ?? $this->storageLocation, + actions: $changes['actions'] ?? $this->actions, + ); + } + + public function withPersistenceIdentifier(string $persistenceIdentifier): self + { + return $this->with(['persistenceIdentifier' => $persistenceIdentifier]); + } + + public function withStorageType(string $storageType): self + { + return $this->with(['storageType' => $storageType]); + } + + public function withDuplicateIdentifier(bool $duplicateIdentifier): self + { + return $this->with(['duplicateIdentifier' => $duplicateIdentifier]); + } + + public function withReadOnly(bool $readOnly): self + { + return $this->with(['readOnly' => $readOnly]); + } + + public function withRemovable(bool $removable): self + { + return $this->with(['removable' => $removable]); + } + + public function withFileUid(?int $fileUid): self + { + return $this->with(['fileUid' => $fileUid]); + } + + public function withReferenceCount(int $referenceCount): self + { + return $this->with(['referenceCount' => $referenceCount]); + } + + public function withInvalid(bool $invalid): self + { + return $this->with(['invalid' => $invalid]); + } + + public function withEditUrl(string $editUrl): self + { + return $this->with(['editUrl' => $editUrl]); + } + + public function withStorageLocation(?string $storageLocation): self + { + return $this->with(['storageLocation' => $storageLocation]); + } + + public function withActions(array $actions): self + { + return $this->with(['actions' => $actions]); + } + + /** + * Returns a comparable scalar value for the given sort field. + * + * Field names in SearchCriteria::ORDER_FIELDS are intentionally kept + * identical to the property names of this class, so a dynamic lookup + * is sufficient. Unknown fields yield null and are skipped by the + * caller. Booleans are cast to int for correct numeric ordering. + */ + public function getSortableValue(string $field): int|string|null + { + if (!property_exists($this, $field)) { + return null; + } + $value = $this->$field; + if (is_bool($value)) { + return (int)$value; + } + return is_int($value) || is_string($value) ? $value : null; + } +} diff --git a/Classes/Domain/DTO/PersistenceManagerConfiguration.php b/Classes/Domain/DTO/PersistenceManagerConfiguration.php new file mode 100644 index 0000000..da54f5f --- /dev/null +++ b/Classes/Domain/DTO/PersistenceManagerConfiguration.php @@ -0,0 +1,81 @@ + + */ + public const DEFAULT_SORT_BY_KEYS = ['name', 'fileUid']; + + /** + * @param list $sortByKeys Keys the forms are sorted by in the form manager and plugin select + * @param list $allowedExtensionPaths EXT: paths that contain forms shipped within extensions + * @param list $allowedFileMounts File mounts forms may be stored in + */ + public function __construct( + public bool $allowSaveToExtensionPaths = false, + public bool $allowDeleteFromExtensionPaths = false, + public array $sortByKeys = self::DEFAULT_SORT_BY_KEYS, + public bool $sortAscending = true, + public array $allowedExtensionPaths = [], + public array $allowedFileMounts = [], + ) {} + + /** + * Create the DTO from the raw "persistenceManager" configuration array. + * + * @param array $configuration + */ + public static function fromArray(array $configuration): self + { + return new self( + allowSaveToExtensionPaths: (bool)($configuration['allowSaveToExtensionPaths'] ?? false), + allowDeleteFromExtensionPaths: (bool)($configuration['allowDeleteFromExtensionPaths'] ?? false), + sortByKeys: self::normalizeStringList($configuration['sortByKeys'] ?? null, self::DEFAULT_SORT_BY_KEYS), + sortAscending: (bool)($configuration['sortAscending'] ?? true), + allowedExtensionPaths: self::normalizeStringList($configuration['allowedExtensionPaths'] ?? null, []), + allowedFileMounts: self::normalizeStringList($configuration['allowedFileMounts'] ?? null, []), + ); + } + + /** + * Normalize a configuration value into a numerically indexed list of strings. + * + * The YAML configuration may use associative keys (e.g. `10:`, `20:`) to + * define ordering, so values are cast to strings and re-indexed. + * + * @param list $default + * @return list + */ + private static function normalizeStringList(mixed $value, array $default): array + { + if (!is_array($value)) { + return $default; + } + + return array_values(array_map(strval(...), $value)); + } +} diff --git a/Classes/Domain/DTO/SearchCriteria.php b/Classes/Domain/DTO/SearchCriteria.php new file mode 100644 index 0000000..0af181e --- /dev/null +++ b/Classes/Domain/DTO/SearchCriteria.php @@ -0,0 +1,152 @@ +$field) instead of an explicit mapping. + */ + private const array ORDER_FIELDS = ['name', 'identifier', 'persistenceIdentifier', 'prototypeName', 'storageLocation', 'duplicateIdentifier', 'referenceCount']; + + public string $orderField; + public string $orderDirection; + + public function __construct( + public ?string $searchTerm = null, + ?string $orderField = null, + ?string $orderDirection = null, + public ?int $limit = null, + ) { + // Validate and normalize orderField + $this->orderField = in_array($orderField, self::ORDER_FIELDS, true) + ? $orderField + : self::DEFAULT_ORDER_FIELD; + + // Validate and normalize orderDirection + $this->orderDirection = in_array($orderDirection, [self::ORDER_ASCENDING, self::ORDER_DESCENDING], true) + ? $orderDirection + : self::ORDER_ASCENDING; + } + + public static function fromArray(array $data): self + { + return new self( + searchTerm: $data['searchTerm'] ?? null, + orderField: $data['orderField'] ?? null, + orderDirection: $data['orderDirection'] ?? null, + limit: $data['limit'] ?? null, + ); + } + + public static function fromRequest(ServerRequestInterface $request): self + { + $queryParams = $request->getQueryParams(); + $parsedBody = $request->getParsedBody() ?? []; + + return new self( + searchTerm: $queryParams['searchTerm'] ?? $parsedBody['searchTerm'] ?? null, + orderField: $queryParams['orderField'] ?? $parsedBody['orderField'] ?? null, + orderDirection: $queryParams['orderDirection'] ?? $parsedBody['orderDirection'] ?? null, + limit: isset($queryParams['limit']) ? (int)$queryParams['limit'] : (isset($parsedBody['limit']) ? (int)$parsedBody['limit'] : null), + ); + } + + public function getOrderField(): string + { + return $this->orderField; + } + + public function getOrderDirection(): string + { + return $this->orderDirection; + } + + public function getDefaultOrderDirection(): string + { + return self::ORDER_ASCENDING; + } + + public function getReverseOrderDirection(): string + { + return $this->orderDirection === self::ORDER_ASCENDING + ? self::ORDER_DESCENDING + : self::ORDER_ASCENDING; + } + + public function getSearchTerm(): ?string + { + return $this->searchTerm; + } + + public function hasSearchTerm(): bool + { + return $this->searchTerm !== null && $this->searchTerm !== ''; + } + + public function getLimit(): ?int + { + return $this->limit; + } + + public function hasLimit(): bool + { + return $this->limit !== null && $this->limit > 0; + } + + /** + * Check if any filter/search constraints are set + */ + public function hasConstraints(): bool + { + return $this->hasSearchTerm() || $this->hasLimit(); + } + + public function getParameters(): array + { + $parameters = []; + if ($this->hasSearchTerm()) { + $parameters['searchTerm'] = $this->searchTerm; + } + if ($this->hasLimit()) { + $parameters['limit'] = $this->limit; + } + $parameters['orderField'] = $this->orderField; + $parameters['orderDirection'] = $this->orderDirection; + return $parameters; + } +} diff --git a/Classes/Domain/DTO/StorageContext.php b/Classes/Domain/DTO/StorageContext.php new file mode 100644 index 0000000..1a36609 --- /dev/null +++ b/Classes/Domain/DTO/StorageContext.php @@ -0,0 +1,36 @@ + + * class MyFooBarFactory extends AbstractFormFactory { + * public function build(array $configuration, $prototypeName) { + * $configurationService = GeneralUtility::makeInstance(ConfigurationService::class); + * $prototypeConfiguration = $configurationService->getPrototypeConfiguration($prototypeName); + * $formDefinition = GeneralUtility::makeInstance(FormDefinition::class, 'nameOfMyForm', $prototypeConfiguration); + * + * // now, you should call methods on $formDefinition to add pages and form elements + * + * return $formDefinition; + * } + * } + * + * + * Scope: frontend / backend + * **This class is meant to be sub classed by developers.** + */ +abstract class AbstractFormFactory implements FormFactoryInterface +{ + protected ?EventDispatcherInterface $eventDispatcher = null; + protected ?FormDefinitionConversionService $formDefinitionConversionService = null; + + public function injectEventDispatcher(EventDispatcherInterface $eventDispatcher): void + { + $this->eventDispatcher = $eventDispatcher; + } + + public function injectFormDefinitionConversionService(FormDefinitionConversionService $formDefinitionConversionService): void + { + $this->formDefinitionConversionService = $formDefinitionConversionService; + } + + protected function triggerFormBuildingFinished(FormDefinition $form): FormDefinition + { + return $this->eventDispatcher->dispatch(new AfterFormIsBuiltEvent($form))->form; + } + + protected function getFormDefinitionConversionService(): FormDefinitionConversionService + { + return $this->formDefinitionConversionService; + } +} diff --git a/Classes/Domain/Factory/ArrayFormFactory.php b/Classes/Domain/Factory/ArrayFormFactory.php new file mode 100644 index 0000000..0230761 --- /dev/null +++ b/Classes/Domain/Factory/ArrayFormFactory.php @@ -0,0 +1,148 @@ +getPrototypeConfiguration($prototypeName); + + // Get RTE property paths for proper sanitization + $rtePropertyPaths = $this->getFormDefinitionConversionService()->extractRtePropertyPaths($prototypeConfiguration); + + $configuration = $this->getFormDefinitionConversionService()->sanitizeHtml($configuration, $rtePropertyPaths); + + if ($configuration['invalid'] ?? false) { + throw new RenderingException($configuration['label'], 1529710560); + } + + $form = GeneralUtility::makeInstance( + FormDefinition::class, + $configuration['identifier'], + $prototypeConfiguration, + 'Form', + $persistenceIdentifier + ); + // Set renderingOptions before processing renderables, so that options + // like 'previewMode' are available during initializeFormElement(). + if (isset($configuration['renderingOptions'])) { + foreach ($configuration['renderingOptions'] as $key => $value) { + $form->setRenderingOption($key, $value); + } + } + if (isset($configuration['renderables'])) { + foreach ($configuration['renderables'] as $pageConfiguration) { + $this->addNestedRenderable($pageConfiguration, $form, $request); + } + } + + unset($configuration['persistenceIdentifier']); + unset($configuration['prototypeName']); + unset($configuration['renderables']); + unset($configuration['type']); + unset($configuration['identifier']); + $form->setOptions($configuration); + $form->setRequest($request); + + return $this->triggerFormBuildingFinished($form); + } + + /** + * Add form elements to the $parentRenderable + * + * @return mixed + * @throws IdentifierNotValidException + * @throws UnknownCompositRenderableException + */ + protected function addNestedRenderable( + array $nestedRenderableConfiguration, + CompositeRenderableInterface $parentRenderable, + ?ServerRequestInterface $request = null + ) { + if (!isset($nestedRenderableConfiguration['identifier'])) { + throw new IdentifierNotValidException('Identifier not set.', 1329289436); + } + if ($parentRenderable instanceof FormDefinition) { + $renderable = $parentRenderable->createPage($nestedRenderableConfiguration['identifier'], $nestedRenderableConfiguration['type']); + } elseif ($parentRenderable instanceof AbstractSection) { + $renderable = $parentRenderable->createElement($nestedRenderableConfiguration['identifier'], $nestedRenderableConfiguration['type']); + if ($request !== null && method_exists($renderable, 'setRequest')) { + $renderable->setRequest($request); + } + } else { + throw new UnknownCompositRenderableException('Unknown composit renderable "' . get_class($parentRenderable) . '"', 1479593622); + } + + $childRenderables = is_array($nestedRenderableConfiguration['renderables'] ?? null) + ? $nestedRenderableConfiguration['renderables'] + : []; + + unset($nestedRenderableConfiguration['type']); + unset($nestedRenderableConfiguration['identifier']); + unset($nestedRenderableConfiguration['renderables']); + + $renderable->setOptions($nestedRenderableConfiguration); + + if ($renderable instanceof CompositeRenderableInterface) { + foreach ($childRenderables as $elementConfiguration) { + $this->addNestedRenderable($elementConfiguration, $renderable, $request); + } + } + + return $this->eventDispatcher->dispatch(new BeforeRenderableIsAddedToFormEvent($renderable))->renderable; + } +} diff --git a/Classes/Domain/Factory/FormFactoryInterface.php b/Classes/Domain/Factory/FormFactoryInterface.php new file mode 100644 index 0000000..a3205f8 --- /dev/null +++ b/Classes/Domain/Factory/FormFactoryInterface.php @@ -0,0 +1,55 @@ +viewFactory = $viewFactory; + } + + public function injectTranslationService(TranslationService $translationService) + { + $this->translationService = $translationService; + } + + /** + * @param string $finisherIdentifier The identifier for this finisher + */ + public function setFinisherIdentifier(string $finisherIdentifier): void + { + $this->finisherIdentifier = $finisherIdentifier; + $this->shortFinisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier) ?? ''; + } + + public function getFinisherIdentifier(): string + { + return $this->finisherIdentifier; + } + + /** + * @param array $options configuration options in the format ['option1' => 'value1', 'option2' => 'value2', ...] + */ + public function setOptions(array $options) + { + $this->options = $options; + } + + /** + * Sets a single finisher option (@see setOptions()) + * + * @param string $optionName name of the option to be set + * @param mixed $optionValue value of the option + */ + public function setOption(string $optionName, $optionValue) + { + $this->options[$optionName] = $optionValue; + } + + /** + * Executes the finisher + * + * @param FinisherContext $finisherContext The Finisher context that contains the current Form Runtime and Response + * @return string|null + */ + final public function execute(FinisherContext $finisherContext) + { + $this->finisherContext = $finisherContext; + + if (!$this->isEnabled()) { + return null; + } + + try { + return $this->executeInternal(); + } catch (FinisherException $e) { + $this->logger->error('Failed to execute finisher', ['exception' => $e]); + $this->finisherContext->cancel(); + $formRuntime = $this->finisherContext->getFormRuntime(); + $renderingOptions = $formRuntime->getRenderingOptions(); + $viewFactoryData = new ViewFactoryData( + templateRootPaths: is_array($renderingOptions['templateRootPaths'] ?? null) ? $renderingOptions['templateRootPaths'] : [], + partialRootPaths: is_array($renderingOptions['partialRootPaths'] ?? null) ? $renderingOptions['partialRootPaths'] : [], + layoutRootPaths: is_array($renderingOptions['layoutRootPaths'] ?? null) ? $renderingOptions['layoutRootPaths'] : [], + request: $this->finisherContext->getRequest(), + ); + $view = $this->viewFactory->create($viewFactoryData); + $message = $this->parseOption('errorMessage') ?: $this->translationService->translate('form.finisher.error', null, 'EXT:form/Resources/Private/Language/locallang.xlf'); + $view->assign('message', $message); + return $view->render('Finishers/Error'); + } + } + + /** + * This method is called in the concrete finisher whenever self::execute() is called. + * + * Override and fill with your own implementation! + * + * @throws FinisherException + * @return string|void|null + */ + abstract protected function executeInternal(); + + /** + * Read the option called $optionName from $this->options, and parse {...} + * as object accessors. + * + * Then translate the value. + * + * If $optionName was not found, the corresponding default option is returned (from $this->defaultOptions) + * + * @param string $optionName + * @return string|array|int|bool|\Closure|callable|null + */ + protected function parseOption(string $optionName) + { + if ($optionName === 'translation') { + return null; + } + + try { + $optionValue = ArrayUtility::getValueByPath($this->options, $optionName, '.'); + } catch (MissingArrayPathException $exception) { + $optionValue = null; + } + try { + $defaultValue = ArrayUtility::getValueByPath($this->defaultOptions, $optionName, '.'); + } catch (MissingArrayPathException $exception) { + $defaultValue = null; + } + + if ($optionValue === null && $defaultValue !== null) { + $optionValue = $defaultValue; + } + + if ($optionValue === null) { + return null; + } + + if (!is_string($optionValue) && !is_array($optionValue)) { + return $optionValue; + } + + $formRuntime = $this->finisherContext->getFormRuntime(); + $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime); + + if (is_string($optionValue)) { + $translationOptions = is_array($this->options['translation'] ?? null) + ? $this->options['translation'] + : []; + + $optionValue = $this->translateFinisherOption( + $optionValue, + $formRuntime, + $optionName, + $optionValue, + $translationOptions + ); + + $optionValue = $this->substituteRuntimeReferences($optionValue, $formRuntime); + } + + if (empty($optionValue)) { + if ($defaultValue !== null) { + $optionValue = $defaultValue; + } + } + return $optionValue; + } + + /** + * Wraps TranslationService::translateFinisherOption to recursively + * invoke all array items of resolved form state values or nested + * finisher option configuration settings. + * + * @param string|array $subject + * @param FormRuntime $formRuntime + * @param string|array $optionValue + * @return array|string + */ + protected function translateFinisherOption( + $subject, + FormRuntime $formRuntime, + string $optionName, + $optionValue, + array $translationOptions + ) { + if (is_array($subject)) { + foreach ($subject as $key => $value) { + $subject[$key] = $this->translateFinisherOption( + $value, + $formRuntime, + $optionName . '.' . $value, + $value, + $translationOptions + ); + } + return $subject; + } + + return $this->translationService->translateFinisherOption( + $formRuntime, + $this->finisherIdentifier, + $optionName, + $optionValue, + $translationOptions + ); + } + + /** + * You can encapsulate an option value with {}. + * This enables you to access every gettable property from the + * TYPO3\CMS\Form\Domain\Runtime\FormRuntime. + * + * For example: {formState.formValues.} + * or {} + * + * Both examples are equal to "$formRuntime->getFormState()->getFormValues()[]" + * There is a special option value '{__currentTimestamp}'. + * This will be replaced with the current timestamp. + * + * @param string|array $needle + * @param FormRuntime $formRuntime + * @return mixed + */ + protected function substituteRuntimeReferences($needle, FormRuntime $formRuntime) + { + // neither array nor string, directly return + if (!is_array($needle) && !is_string($needle)) { + return $needle; + } + + // resolve (recursively) all array items + if (is_array($needle)) { + $substitutedNeedle = []; + foreach ($needle as $key => $item) { + $key = $this->substituteRuntimeReferences($key, $formRuntime); + $item = $this->substituteRuntimeReferences($item, $formRuntime); + $substitutedNeedle[$key] = $item; + } + return $substitutedNeedle; + } + + // substitute one(!) variable in string which either could result + // again in a string or an array representing multiple values + if (preg_match('/^{([^}]+)}$/', $needle, $matches)) { + return $this->resolveRuntimeReference( + $matches[1], + $formRuntime + ); + } + + // in case string contains more than just one variable or just a static + // value that does not need to be substituted at all, candidates are: + // * "prefix{variable}suffix + // * "{variable-1},{variable-2}" + // * "some static value" + // * mixed cases of the above + return preg_replace_callback( + '/{([^}]+)}/', + function ($matches) use ($formRuntime) { + $value = $this->resolveRuntimeReference( + $matches[1], + $formRuntime + ); + + // substitute each match by returning the resolved value + if (!is_array($value)) { + return $value; + } + + // now the resolve value is an array that shall substitute + // a variable in a string that probably is not the only one + // or is wrapped with other static string content (see above) + // ... which is just not possible + throw new FinisherException( + 'Cannot convert array to string', + 1519239265 + ); + }, + $needle + ); + } + + /** + * Resolving property by name from submitted form data. + * + * @return int|string|array + */ + protected function resolveRuntimeReference(string $property, FormRuntime $formRuntime) + { + if ($property === '__currentTimestamp') { + return time(); + } + + // try to resolve the path '{...}' within the FormRuntime + $value = ObjectAccess::getPropertyPath($formRuntime, $property); + + if (is_object($value)) { + $element = $formRuntime->getFormDefinition()->getElementByIdentifier($property); + + if (!$element instanceof StringableFormElementInterface) { + throw new FinisherException( + sprintf('Cannot convert object value of "%s" to string', $property), + 1574362327 + ); + } + + $value = $element->valueToString($value); + } + + if ($value === null) { + // try to resolve the path '{...}' within the FinisherVariableProvider + $value = ObjectAccess::getPropertyPath( + $this->finisherContext->getFinisherVariableProvider(), + $property + ); + } + + if ($value !== null) { + return $value; + } + + // in case no value could be resolved + return '{' . $property . '}'; + } + + /** + * Returns whether this finisher is enabled + */ + public function isEnabled(): bool + { + return !isset($this->options['renderingOptions']['enabled']) || (bool)$this->parseOption('renderingOptions.enabled') === true; + } +} diff --git a/Classes/Domain/Finishers/ClosureFinisher.php b/Classes/Domain/Finishers/ClosureFinisher.php new file mode 100644 index 0000000..f103cb9 --- /dev/null +++ b/Classes/Domain/Finishers/ClosureFinisher.php @@ -0,0 +1,67 @@ +setOption('closure', function($finisherContext) { + * $formRuntime = $finisherContext->getFormRuntime(); + * // ... + * }); + * $formDefinition->addFinisher($closureFinisher); + * // ... + * + * Scope: frontend + */ +class ClosureFinisher extends AbstractFinisher +{ + /** + * @var array + */ + protected $defaultOptions = [ + 'closure' => null, + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @throws FinisherException + */ + protected function executeInternal() + { + $closure = $this->parseOption('closure'); + if ($closure === null) { + return; + } + if (!$closure instanceof \Closure) { + throw new FinisherException(sprintf('The option "closure" must be of type Closure, "%s" given.', gettype($closure)), 1332155239); + } + $closure($this->finisherContext); + } +} diff --git a/Classes/Domain/Finishers/ConfirmationFinisher.php b/Classes/Domain/Finishers/ConfirmationFinisher.php new file mode 100644 index 0000000..610165f --- /dev/null +++ b/Classes/Domain/Finishers/ConfirmationFinisher.php @@ -0,0 +1,127 @@ +setOptions( + * [ + * 'message' => 'foo', + * ] + * ); + * $formDefinition->addFinisher($confirmationFinisher); + * // ... + * + * Scope: frontend + */ +class ConfirmationFinisher extends AbstractFinisher +{ + /** + * @var array + */ + protected $defaultOptions = [ + 'message' => 'The form has been submitted.', + 'contentElementUid' => 0, + 'typoscriptObjectPath' => 'lib.tx_form.contentElementRendering', + ]; + + public function __construct( + private readonly ExtbaseConfigurationManagerInterface $extbaseConfigurationManager, + private readonly ViewFactoryInterface $viewFactory, + ) {} + + /** + * @throws FinisherException + */ + protected function executeInternal(): string + { + $options = $this->options; + if (!isset($options['templateName']) || !is_string($options['templateName'])) { + throw new FinisherException( + 'The option "templateName" must be set for the ConfirmationFinisher.', + 1521573955 + ); + } + + $contentElementUid = $this->parseOption('contentElementUid'); + $typoscriptObjectPath = $this->parseOption('typoscriptObjectPath'); + $typoscriptObjectPath = is_string($typoscriptObjectPath) ? $typoscriptObjectPath : ''; + if (!empty($contentElementUid)) { + $pathSegments = GeneralUtility::trimExplode('.', $typoscriptObjectPath); + $lastSegment = array_pop($pathSegments); + $setup = $this->extbaseConfigurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); + foreach ($pathSegments as $segment) { + if (!array_key_exists($segment . '.', $setup)) { + throw new FinisherException( + sprintf('TypoScript object path "%s" does not exist', $typoscriptObjectPath), + 1489238980 + ); + } + $setup = $setup[$segment . '.']; + } + $contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class); + $contentObjectRenderer->setRequest($this->finisherContext->getRequest()->withoutAttribute('extbase')); + $contentObjectRenderer->start([$contentElementUid]); + $contentObjectRenderer->setCurrentVal((string)$contentElementUid); + $message = $contentObjectRenderer->cObjGetSingle($setup[$lastSegment], $setup[$lastSegment . '.'], $lastSegment); + } else { + $message = $this->parseOption('message'); + } + + $formRuntime = $this->finisherContext->getFormRuntime(); + $viewFactoryData = new ViewFactoryData( + templateRootPaths: is_array($options['templateRootPaths'] ?? null) ? $options['templateRootPaths'] : [], + partialRootPaths: is_array($options['partialRootPaths'] ?? null) ? $options['partialRootPaths'] : [], + layoutRootPaths: is_array($options['layoutRootPaths'] ?? null) ? $options['layoutRootPaths'] : [], + request: $this->finisherContext->getRequest(), + ); + $view = $this->viewFactory->create($viewFactoryData); + if ($view instanceof FluidViewAdapter) { + $view->getRenderingContext()->getViewHelperVariableContainer() + ->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $formRuntime); + } + if (is_array($this->options['variables'] ?? null)) { + $view->assignMultiple($this->options['variables']); + } + $view->assignMultiple([ + 'form' => $formRuntime, + 'finisherVariableProvider' => $this->finisherContext->getFinisherVariableProvider(), + 'message' => $message, + 'isPreparedMessage' => !empty($contentElementUid), + ]); + return $view->render($options['templateName']); + } +} diff --git a/Classes/Domain/Finishers/DeleteUploadsFinisher.php b/Classes/Domain/Finishers/DeleteUploadsFinisher.php new file mode 100644 index 0000000..a407bdd --- /dev/null +++ b/Classes/Domain/Finishers/DeleteUploadsFinisher.php @@ -0,0 +1,109 @@ +finisherContext->getFormRuntime(); + + $uploadFolders = []; + $elements = $formRuntime->getFormDefinition()->getRenderablesRecursively(); + foreach ($elements as $element) { + if (!$element instanceof FileUpload) { + continue; + } + $file = $formRuntime[$element->getIdentifier()]; + if (!$file) { + continue; + } + + if ($file instanceof ExtbaseFileReference) { + $file = $file->getOriginalResource(); + } + if ($file instanceof FileReference) { + $this->deleteFileAndCollectFolder($file, $uploadFolders); + } elseif ($file instanceof ObjectStorage) { + foreach ($file as $singleFile) { + if ($singleFile instanceof ExtbaseFileReference) { + $singleFile = $singleFile->getOriginalResource(); + } + if ($singleFile instanceof FileReference) { + $this->deleteFileAndCollectFolder($singleFile, $uploadFolders); + } + } + } + + } + + $this->deleteEmptyUploadFolders($uploadFolders); + } + + /** + * Deletes the file and collects its parent folder for later cleanup. + * + * @param array $uploadFolders + */ + private function deleteFileAndCollectFolder(FileReference $file, array &$uploadFolders): void + { + $folder = $file->getParentFolder(); + if ($folder instanceof Folder) { + $uploadFolders[$folder->getCombinedIdentifier()] = $folder; + } + $file->getStorage()->deleteFile($file->getOriginalFile()); + } + + /** + * note: + * TYPO3\CMS\Form\Mvc\Property\TypeConverter\UploadedFileReferenceConverter::importUploadedResource() + * creates a sub-folder for file uploads (e.g. .../form_<40-chars-hash>/actual.file) + * @param Folder[] $folders + */ + protected function deleteEmptyUploadFolders(array $folders): void + { + foreach ($folders as $folder) { + if ($this->isEmptyFolder($folder)) { + $folder->delete(); + } + } + } + + protected function isEmptyFolder(Folder $folder): bool + { + return $folder->getFileCount() === 0 + && $folder->getStorage()->countFoldersInFolder($folder) === 0; + } +} diff --git a/Classes/Domain/Finishers/EmailFinisher.php b/Classes/Domain/Finishers/EmailFinisher.php new file mode 100644 index 0000000..5ec763a --- /dev/null +++ b/Classes/Domain/Finishers/EmailFinisher.php @@ -0,0 +1,268 @@ + '', + 'senderName' => '', + 'addHtmlPart' => true, + 'attachUploads' => true, + ]; + + public function __construct( + protected readonly EventDispatcherInterface $eventDispatcher, + protected readonly TemplatedEmailFactory $templatedEmailFactory, + protected readonly MailerInterface $mailer, + ) {} + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @throws FinisherException + */ + protected function executeInternal(): void + { + $this->options = $this->eventDispatcher + ->dispatch(new BeforeEmailFinisherInitializedEvent($this->finisherContext, $this->options)) + ->getOptions(); + // Flexform overrides write strings instead of integers so + // we need to cast the string '0' to false. + if ( + isset($this->options['addHtmlPart']) + && $this->options['addHtmlPart'] === '0' + ) { + $this->options['addHtmlPart'] = false; + } + + $subject = (string)$this->parseOption('subject'); + $recipients = $this->getRecipients('recipients'); + $senderAddress = $this->parseOption('senderAddress'); + $senderAddress = is_string($senderAddress) ? $senderAddress : ''; + $senderName = $this->parseOption('senderName'); + $senderName = is_string($senderName) ? $senderName : ''; + $replyToRecipients = $this->getRecipients('replyToRecipients'); + $carbonCopyRecipients = $this->getRecipients('carbonCopyRecipients'); + $blindCarbonCopyRecipients = $this->getRecipients('blindCarbonCopyRecipients'); + $addHtmlPart = (bool)$this->parseOption('addHtmlPart'); + $attachUploads = $this->parseOption('attachUploads'); + $title = (string)$this->parseOption('title') ?: $subject; + + if ($subject === '') { + throw new FinisherException('The option "subject" must be set for the EmailFinisher.', 1327060320); + } + if (empty($recipients)) { + throw new FinisherException('The option "recipients" must be set for the EmailFinisher.', 1327060200); + } + if (empty($senderAddress)) { + throw new FinisherException('The option "senderAddress" must be set for the EmailFinisher.', 1327060210); + } + + $formRuntime = $this->finisherContext->getFormRuntime(); + + $mail = $this + ->initializeFluidEmail($formRuntime) + ->from(new Address($senderAddress, $senderName)) + ->to(...$recipients) + ->subject($subject) + ->format($addHtmlPart ? FluidEmail::FORMAT_BOTH : FluidEmail::FORMAT_PLAIN) + ->assign('title', $title); + + if (!empty($replyToRecipients)) { + $mail->replyTo(...$replyToRecipients); + } + + if (!empty($carbonCopyRecipients)) { + $mail->cc(...$carbonCopyRecipients); + } + + if (!empty($blindCarbonCopyRecipients)) { + $mail->bcc(...$blindCarbonCopyRecipients); + } + + if (is_string($this->options['translation']['language'] ?? null) && $this->options['translation']['language'] !== '') { + $mail->assign('languageKey', $this->options['translation']['language']); + } + + $message = $this->parseOption('message'); + if (is_string($message) && $message !== '') { + // Remove whitespace between HTML tags to prevent lib.parseFunc_RTE + // from converting newlines into additional blank lines in the email output + $message = preg_replace('/>\s+<', $message); + $placeholderPos = strpos($message, '{formValues}'); + if ($placeholderPos !== false) { + $mail->assign('messageBefore', substr($message, 0, $placeholderPos)); + $mail->assign('messageAfter', substr($message, $placeholderPos + strlen('{formValues}'))); + } else { + // No placeholder - show message only, no form values + $mail->assign('messageBefore', $message); + $mail->assign('messageAfter', ''); + $mail->assign('hideFormValues', true); + } + } + + if ($attachUploads) { + foreach ($formRuntime->getFormDefinition()->getRenderablesRecursively() as $element) { + if (!$element instanceof FileUpload) { + continue; + } + $file = $formRuntime[$element->getIdentifier()]; + if ($file instanceof FileReference) { + $file = $file->getOriginalResource(); + } + if ($file instanceof FileInterface) { + $mail->attach($file->getContents(), $file->getName(), $file->getMimeType()); + } elseif ($file instanceof ObjectStorage) { + foreach ($file as $singleFile) { + if ($singleFile instanceof FileReference) { + $singleFile = $singleFile->getOriginalResource(); + } + if ($singleFile instanceof FileInterface) { + $mail->attach($singleFile->getContents(), $singleFile->getName(), $singleFile->getMimeType()); + } + } + } + } + } + + try { + $this->mailer->send($mail); + } catch (TransportExceptionInterface $e) { + throw new FinisherException( + 'Failed to send the email: ' . $e->getMessage(), + 1754047320, + $e + ); + } + } + + protected function initializeFluidEmail(FormRuntime $formRuntime): FluidEmail + { + $mailMessage = $this->templatedEmailFactory->createWithOverrides( + $this->options['templateRootPaths'] ?? [], + $this->options['layoutRootPaths'] ?? [], + $this->options['partialRootPaths'] ?? [], + $this->finisherContext->getRequest(), + ); + + if (!isset($this->options['templateName']) || $this->options['templateName'] === '') { + throw new FinisherException('The option "templateName" must be set to use FluidEmail.', 1599834020); + } + + // Migrate old template name to default FluidEmail name + if ($this->options['templateName'] === '{@format}.html') { + $this->options['templateName'] = 'Default'; + } + + $mailMessage + ->setTemplate($this->options['templateName']) + ->assignMultiple([ + 'finisherVariableProvider' => $this->finisherContext->getFinisherVariableProvider(), + 'form' => $formRuntime, + ]); + + if (is_array($this->options['variables'] ?? null)) { + $mailMessage->assignMultiple($this->options['variables']); + } + + $mailMessage + ->getViewHelperVariableContainer() + ->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $formRuntime); + + return $mailMessage; + } + + protected function getRecipients(string $listOption): array + { + $recipients = $this->parseOption($listOption) ?? []; + if (!is_array($recipients) || $recipients === []) { + return []; + } + + $addresses = []; + foreach ($recipients as $address => $name) { + // The if is needed to set address and name with TypoScript + if (MathUtility::canBeInterpretedAsInteger($address)) { + if (is_array($name)) { + $address = $name[0] ?? ''; + $name = $name[1] ?? ''; + } else { + $address = $name; + $name = ''; + } + } + + $address = trim((string)$address); + + if (!GeneralUtility::validEmail($address)) { + // Drop entries without a valid address + continue; + } + $addresses[] = new Address($address, $name); + } + return $addresses; + } +} diff --git a/Classes/Domain/Finishers/Exception/FinisherException.php b/Classes/Domain/Finishers/Exception/FinisherException.php new file mode 100644 index 0000000..71f3049 --- /dev/null +++ b/Classes/Domain/Finishers/Exception/FinisherException.php @@ -0,0 +1,25 @@ +formRuntime = $formRuntime; + $this->request = $request; + $this->finisherVariableProvider = new FinisherVariableProvider(); + } + + /** + * Cancels the finisher invocation after the current finisher + */ + public function cancel() + { + $this->cancelled = true; + } + + /** + * TRUE if no further finishers should be invoked. Defaults to FALSE + * + * @internal + */ + public function isCancelled(): bool + { + return $this->cancelled; + } + + /** + * The Form Runtime that is associated with the current finisher + */ + public function getFormRuntime(): FormRuntime + { + return $this->formRuntime; + } + + /** + * The values of the submitted form (after validation and property mapping) + */ + public function getFormValues(): array + { + return $this->formRuntime->getFormState()->getFormValues(); + } + + public function getFinisherVariableProvider(): FinisherVariableProvider + { + return $this->finisherVariableProvider; + } + + public function getRequest(): Request + { + return $this->request; + } +} diff --git a/Classes/Domain/Finishers/FinisherInterface.php b/Classes/Domain/Finishers/FinisherInterface.php new file mode 100644 index 0000000..8a2bd90 --- /dev/null +++ b/Classes/Domain/Finishers/FinisherInterface.php @@ -0,0 +1,59 @@ + 'value1', 'option2' => 'value2', ...] + */ + public function setOptions(array $options); + + /** + * Sets a single finisher option (@see setOptions()) + * + * @param string $optionName name of the option to be set + * @param mixed $optionValue value of the option + */ + public function setOption(string $optionName, $optionValue); + + /** + * Returns whether this finisher is enabled + */ + public function isEnabled(): bool; +} diff --git a/Classes/Domain/Finishers/FinisherVariableProvider.php b/Classes/Domain/Finishers/FinisherVariableProvider.php new file mode 100644 index 0000000..d07fada --- /dev/null +++ b/Classes/Domain/Finishers/FinisherVariableProvider.php @@ -0,0 +1,187 @@ +addOrUpdate($finisherIdentifier, $key, $value); + } + + /** + * Add a variable to the Variable Container. + * In case the value is already inside, it is silently overridden. + * + * @param mixed $value + */ + public function addOrUpdate(string $finisherIdentifier, string $key, $value) + { + if (!array_key_exists($finisherIdentifier, $this->objects)) { + $this->objects[$finisherIdentifier] = []; + } + $this->objects[$finisherIdentifier] = ArrayUtility::setValueByPath( + $this->objects[$finisherIdentifier], + $key, + $value, + '.' + ); + } + + /** + * Gets a variable which is stored + * + * @param mixed $default + * @return mixed + */ + public function get(string $finisherIdentifier, string $key, $default = null) + { + if ($this->exists($finisherIdentifier, $key)) { + return ArrayUtility::getValueByPath($this->objects[$finisherIdentifier], $key, '.'); + } + return $default; + } + + /** + * Determine whether there is a variable stored for the given key + * + * @param string $finisherIdentifier + * @param string $key + */ + public function exists($finisherIdentifier, $key): bool + { + try { + ArrayUtility::getValueByPath($this->objects[$finisherIdentifier] ?? [], $key, '.'); + } catch (MissingArrayPathException $e) { + return false; + } + return true; + } + + /** + * Remove a value from the variable container + */ + public function remove(string $finisherIdentifier, string $key) + { + if ($this->exists($finisherIdentifier, $key)) { + $this->objects[$finisherIdentifier] = ArrayUtility::removeByPath( + $this->objects[$finisherIdentifier], + $key, + '.' + ); + } + } + + /** + * Clean up for serializing. + * + * @return array + */ + public function __sleep() + { + return ['objects']; + } + + /** + * Whether an offset exists + * + * @link https://php.net/manual/en/arrayaccess.offsetexists.php + * @param mixed $offset An offset to check for. + * @return bool TRUE on success or FALSE on failure. + */ + public function offsetExists(mixed $offset): bool + { + return isset($this->objects[$offset]); + } + + /** + * Offset to retrieve + * + * @link https://php.net/manual/en/arrayaccess.offsetget.php + * @param mixed $offset The offset to retrieve. + * @return mixed Can return all value types. + */ + public function offsetGet(mixed $offset): mixed + { + return $this->objects[$offset]; + } + + /** + * Offset to set + * + * @link https://php.net/manual/en/arrayaccess.offsetset.php + * @param mixed $offset The offset to assign the value to. + * @param mixed $value The value to set. + */ + public function offsetSet(mixed $offset, mixed $value): void + { + $this->objects[$offset] = $value; + } + + /** + * Offset to unset + * + * @link https://php.net/manual/en/arrayaccess.offsetunset.php + * @param mixed $offset The offset to unset. + */ + public function offsetUnset(mixed $offset): void + { + unset($this->objects[$offset]); + } + + public function getIterator(): \Traversable + { + foreach ($this->objects as $offset => $value) { + yield $offset => $value; + } + } + + /** + * Count elements of an object + * + * @link https://php.net/manual/en/countable.count.php + * @return int The custom count as an integer. + */ + public function count(): int + { + return count($this->objects); + } +} diff --git a/Classes/Domain/Finishers/FlashMessageFinisher.php b/Classes/Domain/Finishers/FlashMessageFinisher.php new file mode 100644 index 0000000..c75723d --- /dev/null +++ b/Classes/Domain/Finishers/FlashMessageFinisher.php @@ -0,0 +1,128 @@ +setOptions( + * [ + * 'messageBody' => 'Some message body', + * 'messageTitle' => 'Some message title', + * 'messageArguments' => ['foo' => 'bar'], + * 'severity' => \TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::ERROR + * ] + * ); + * $formDefinition->addFinisher($flashMessageFinisher); + * // ... + * + * Scope: frontend + */ +class FlashMessageFinisher extends AbstractFinisher +{ + /** + * @var array + */ + protected $defaultOptions = [ + 'messageBody' => null, + 'messageTitle' => '', + 'messageArguments' => [], + 'messageCode' => null, + 'severity' => ContextualFeedbackSeverity::OK, + ]; + + private ExtensionService $extensionService; + private FlashMessageService $flashMessageService; + + public function injectFlashMessageService(FlashMessageService $flashMessageService): void + { + $this->flashMessageService = $flashMessageService; + } + + public function injectExtensionService(ExtensionService $extensionService): void + { + $this->extensionService = $extensionService; + } + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @throws FinisherException + */ + protected function executeInternal() + { + $messageBody = $this->parseOption('messageBody'); + if (!is_string($messageBody)) { + throw new FinisherException(sprintf('The message body must be of type string, "%s" given.', gettype($messageBody)), 1335980069); + } + $messageTitle = $this->parseOption('messageTitle'); + $messageArguments = $this->parseOption('messageArguments'); + $messageCode = $this->parseOption('messageCode'); + $severity = $this->parseOption('severity'); + + if (MathUtility::canBeInterpretedAsInteger($severity)) { + $severity = ContextualFeedbackSeverity::tryFrom((int)$severity); + } + if (!$severity instanceof ContextualFeedbackSeverity) { + $severity = $this->defaultOptions['severity']; + } + + $messageClass = match ($severity) { + ContextualFeedbackSeverity::NOTICE => Notice::class, + ContextualFeedbackSeverity::WARNING => Warning::class, + ContextualFeedbackSeverity::ERROR => Error::class, + default => Message::class, + }; + /** @var Message|Notice|Warning|Error $message */ + $message = GeneralUtility::makeInstance($messageClass, $messageBody, $messageCode, $messageArguments, $messageTitle); + $flashMessage = new FlashMessage( + $message->render(), + $message->getTitle(), + $severity, + true + ); + + // todo: this value has to be taken from the request directly in the future + $pluginNamespace = $this->extensionService->getPluginNamespace( + $this->finisherContext->getRequest()->getControllerExtensionName(), + $this->finisherContext->getRequest()->getPluginName() + ); + + $this->flashMessageService->getMessageQueueByIdentifier('extbase.flashmessages.' . $pluginNamespace)->addMessage($flashMessage); + } +} diff --git a/Classes/Domain/Finishers/RedirectFinisher.php b/Classes/Domain/Finishers/RedirectFinisher.php new file mode 100644 index 0000000..2019d6e --- /dev/null +++ b/Classes/Domain/Finishers/RedirectFinisher.php @@ -0,0 +1,110 @@ + 1, + 'additionalParameters' => '', + 'statusCode' => 303, + 'fragment' => '', + ]; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + */ + protected function executeInternal(): void + { + $pageUid = $this->parseOption('pageUid'); + $pageUid = (int)str_replace('pages_', '', (string)$pageUid); + $additionalParameters = $this->parseOption('additionalParameters'); + $additionalParameters = is_string($additionalParameters) ? $additionalParameters : ''; + $additionalParameters = '&' . ltrim($additionalParameters, '&'); + $statusCode = (int)$this->parseOption('statusCode'); + $fragment = (string)$this->parseOption('fragment'); + + $this->finisherContext->cancel(); + $this->redirect($pageUid, $additionalParameters, $fragment, $statusCode); + } + + /** + * Redirects the request to another page. + * + * Redirect will be sent to the client which then performs another request to the new URI. + * + * NOTE: This method only supports web requests and will thrown an exception + * if used with other request types. + * + * @param int $pageUid Target page uid. If NULL, the current page uid is used + * @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other" + * @see forward() + */ + protected function redirect(int $pageUid, string $additionalParameters, string $fragment, int $statusCode): never + { + $redirectUri = $this->finisherContext->getRequest()->getAttribute('currentContentObject')->createUrl([ + 'parameter' => $pageUid, + 'additionalParams' => $additionalParameters, + 'section' => $fragment, + ]); + $this->redirectToUri($redirectUri, $statusCode); + } + + /** + * Redirects the web request to another uri. + * + * NOTE: This method only supports web requests and will throw an exception if used with other request types. + * + * @param string $uri A string representation of a URI + * @param int $statusCode (optional) The HTTP status code for the redirect. Default is "303 See Other + * @throws PropagateResponseException + */ + protected function redirectToUri(string $uri, int $statusCode = 303): never + { + $uri = $this->addBaseUriIfNecessary($uri); + $response = new RedirectResponse($uri, $statusCode); + // End processing and dispatching by throwing a PropagateResponseException with our response. + // @todo: Should be changed to *return* a response instead, but this requires the ContentObjectRender + // @todo: to deal with responses instead of strings, if the form is used in a fluid template rendered by the + // @todo: FluidTemplateContentObject and the extbase bootstrap isn't used. + throw new PropagateResponseException($response, 1477070964); + } + + /** + * Adds the base uri if not already in place. + * + * @param string $uri The URI + */ + protected function addBaseUriIfNecessary(string $uri): string + { + return GeneralUtility::locationHeaderUrl($uri, $this->finisherContext->getRequest()); + } +} diff --git a/Classes/Domain/Finishers/SaveToDatabaseFinisher.php b/Classes/Domain/Finishers/SaveToDatabaseFinisher.php new file mode 100644 index 0000000..96bb877 --- /dev/null +++ b/Classes/Domain/Finishers/SaveToDatabaseFinisher.php @@ -0,0 +1,407 @@ +.mapOnDatabaseColumn (mandatory) + * -------------------------------------------------------- + * The value from the submitted form element with the identifier + * '' will be written into this database column + * + * options.elements..skipIfValueIsEmpty (default: false) + * ------------------------------------------------------ + * Set this to true if the database column should not be written + * if the value from the submitted form element with the identifier + * '' is empty (think about password fields etc.) + * + * options.elements..hashed (default: false) + * ------------------------------------------------------ + * Set this to true if the value from the submitted form element + * should be hashed before writing into the database. + * + * options.elements..saveFileIdentifierInsteadOfUid (default: false) + * ------------------------------------------------------------------- + * This setting only rules for form elements which creates a FAL object + * like FileUpload or ImageUpload. + * By default, the uid of the FAL object will be written into + * the database column. Set this to true if you want to store the + * FAL identifier (1:/user_uploads/some_uploaded_pic.jpg) instead. + * + * options.databaseColumnMappings + * ------------------------------ + * Use this to map database columns to static values (which can be + * made dynamic through typoscript overrides of course). + * Each key within options.databaseColumnMappings has to match with a + * existing database column. + * The value for each key within options.databaseColumnMappings is an + * array with additional information. + * + * This mapping is done *before* the options.elements mapping. + * This means if you map a database column to a value through + * options.databaseColumnMappings and map a submitted form element + * value to the same database column, the submitted form element value + * will override the value you set within options.databaseColumnMappings. + * + * options.databaseColumnMappings..value + * --------------------------------------------------------- + * The value which will be written to the database column. + * You can use the FormRuntime accessor feature to access every + * getable property from the TYPO3\CMS\Form\Domain\Runtime\FormRuntime + * Read the description within + * TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher::parseOption + * In short: use something like {} to get the value + * from the submitted form element with the identifier + * + * + * Don't be confused. If you use the FormRuntime accessor feature within + * options.databaseColumnMappings, the functionality is nearly equal + * to the options.elements configuration. + * + * options.databaseColumnMappings..skipIfValueIsEmpty (default: false) + * --------------------------------------------------------------------- + * Set this to true if the database column should not be written + * if the value from + * options.databaseColumnMappings..value is empty. + * + * Example + * ======= + * + * finishers: + * - + * identifier: SaveToDatabase + * options: + * table: 'fe_users' + * mode: update + * whereClause: + * uid: 1 + * databaseColumnMappings: + * pid: + * value: 1 + * elements: + * text-1: + * mapOnDatabaseColumn: 'first_name' + * text-2: + * mapOnDatabaseColumn: 'last_name' + * text-3: + * mapOnDatabaseColumn: 'username' + * advancedpassword-1: + * mapOnDatabaseColumn: 'password' + * skipIfValueIsEmpty: true + * hashed: true + * + * Multiple database operations + * ============================ + * + * You can write options as an array to perform multiple database operations. + * + * finishers: + * - + * identifier: SaveToDatabase + * options: + * 1: + * table: 'my_table' + * mode: insert + * databaseColumnMappings: + * some_column: + * value: 'cool' + * 2: + * table: 'my_other_table' + * mode: update + * whereClause: + * pid: 1 + * databaseColumnMappings: + * some_other_column: + * value: '{SaveToDatabase.insertedUids.1}' + * + * This would perform 2 database operations. + * One insert and one update. + * You can access the inserted uids with '{SaveToDatabase.insertedUids.}' + * If you perform an insert operation, the value of the inserted database row will be stored + * within the FinisherVariableProvider. + * references to the numeric key within options + * within which the insert operation is executed. + * + * Scope: frontend + */ +class SaveToDatabaseFinisher extends AbstractFinisher +{ + /** + * @var array + */ + protected $defaultOptions = [ + 'table' => null, + 'mode' => 'insert', + 'whereClause' => [], + 'elements' => [], + 'databaseColumnMappings' => [], + ]; + + /** + * @var \TYPO3\CMS\Core\Database\Connection + */ + protected $databaseConnection; + + /** + * Executes this finisher + * @see AbstractFinisher::execute() + * + * @throws FinisherException + */ + protected function executeInternal(): void + { + $options = []; + if (isset($this->options['table'])) { + $options[] = $this->options; + } else { + $options = $this->options; + } + + foreach ($options as $optionKey => $option) { + $this->options = $option; + $this->process($optionKey); + } + } + + /** + * Prepare data for saving to database + */ + protected function prepareData(array $elementsConfiguration, array $databaseData): array + { + foreach ($this->getFormValues() as $elementIdentifier => $elementValue) { + if ( + ($elementValue === null || $elementValue === '') + && isset($elementsConfiguration[$elementIdentifier]) + && isset($elementsConfiguration[$elementIdentifier]['skipIfValueIsEmpty']) + && $elementsConfiguration[$elementIdentifier]['skipIfValueIsEmpty'] === true + ) { + continue; + } + + $element = $this->getElementByIdentifier($elementIdentifier); + if ( + !$element + || !isset($elementsConfiguration[$elementIdentifier]) + || !isset($elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']) + ) { + continue; + } + + if (isset($elementsConfiguration[$elementIdentifier]['saveFileIdentifierInsteadOfUid'])) { + $saveFileIdentifierInsteadOfUid = (bool)$elementsConfiguration[$elementIdentifier]['saveFileIdentifierInsteadOfUid']; + } else { + $saveFileIdentifierInsteadOfUid = false; + } + + if ($elementValue instanceof FileReference) { + $elementValue = $this->prepareFileForDatabase($elementValue, $saveFileIdentifierInsteadOfUid); + } elseif ($elementValue instanceof ObjectStorage) { + $fileIdentifiers = []; + foreach ($elementValue as $singleElement) { + if ($singleElement instanceof FileReference) { + $fileIdentifiers[] = $this->prepareFileForDatabase($singleElement, $saveFileIdentifierInsteadOfUid); + } + } + $elementValue = implode(',', $fileIdentifiers); + } elseif (is_array($elementValue)) { + $elementValue = implode(',', $elementValue); + } elseif ($elementValue instanceof \DateTimeInterface) { + $format = $elementsConfiguration[$elementIdentifier]['dateFormat'] ?? 'U'; + $elementValue = $elementValue->format($format); + } elseif ($elementValue && ($elementsConfiguration[$elementIdentifier]['hashed'] ?? false) === true) { + $hashInstance = GeneralUtility::makeInstance(PasswordHashFactory::class)->getDefaultHashInstance('FE'); + $elementValue = $hashInstance->getHashedPassword($elementValue); + } + + $databaseData[$elementsConfiguration[$elementIdentifier]['mapOnDatabaseColumn']] = $elementValue; + } + return $databaseData; + } + + /** + * Perform the current database operation + * @throws FinisherException + */ + protected function process(int $iterationCount): void + { + $this->throwExceptionOnInconsistentConfiguration(); + + $table = $this->parseOption('table'); + $table = is_string($table) ? $table : ''; + $elementsConfiguration = $this->parseOption('elements'); + $elementsConfiguration = is_array($elementsConfiguration) ? $elementsConfiguration : []; + $databaseColumnMappingsConfiguration = $this->parseOption('databaseColumnMappings'); + + $this->databaseConnection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table); + + $databaseData = []; + foreach ($databaseColumnMappingsConfiguration as $databaseColumnName => $databaseColumnConfiguration) { + $value = $this->parseOption('databaseColumnMappings.' . $databaseColumnName . '.value'); + if ( + empty($value) + && ($databaseColumnConfiguration['skipIfValueIsEmpty'] ?? false) === true + ) { + continue; + } + + $databaseData[$databaseColumnName] = $value; + } + + $databaseData = $this->prepareData($elementsConfiguration, $databaseData); + + try { + $this->saveToDatabase($databaseData, $table, $iterationCount); + } catch (Exception $e) { + throw new FinisherException( + 'Failed to save data to database table: ' . $table . '. Error message:' . $e->getMessage(), + 1754050114, + $e + ); + } + } + + /** + * Save or insert the values from + * $databaseData into the table $table + * @throws Exception + */ + protected function saveToDatabase(array $databaseData, string $table, int $iterationCount): void + { + if (!empty($databaseData)) { + if ($this->parseOption('mode') === 'update') { + $whereClause = $this->parseOption('whereClause'); + foreach ($whereClause as $columnName => $columnValue) { + $whereClause[$columnName] = $this->parseOption('whereClause.' . $columnName); + } + $this->databaseConnection->update( + $table, + $databaseData, + $whereClause + ); + } else { + $this->databaseConnection->insert($table, $databaseData); + try { + $insertedUid = (int)$this->databaseConnection->lastInsertId(); + } catch (Exception) { + // Some database tables like sys_category_record_mm may not + // have an "identity" (uid column). In this case DBAL may + // throw an exception, which we gracefully handle here. + $insertedUid = 0; + } + $this->finisherContext->getFinisherVariableProvider()->add( + $this->shortFinisherIdentifier, + 'insertedUids.' . $iterationCount, + $insertedUid + ); + } + } + } + + /** + * Throws an exception if some inconsistent configuration + * are detected. + * + * @throws FinisherException + */ + protected function throwExceptionOnInconsistentConfiguration(): void + { + if ( + $this->parseOption('mode') === 'update' + && empty($this->parseOption('whereClause')) + ) { + throw new FinisherException( + 'An empty option "whereClause" is not allowed in update mode.', + 1480469086 + ); + } + } + + /** + * Returns the values of the submitted form + */ + protected function getFormValues(): array + { + return $this->finisherContext->getFormValues(); + } + + /** + * Returns a form element object for a given identifier. + * + * @return FormElementInterface|null + */ + protected function getElementByIdentifier(string $elementIdentifier): ?FormElementInterface + { + return $this + ->finisherContext + ->getFormRuntime() + ->getFormDefinition() + ->getElementByIdentifier($elementIdentifier); + } + + protected function prepareFileForDatabase(FileReference $fileReference, bool $saveFileIdentifierInsteadOfUid = false): int|string + { + if ($saveFileIdentifierInsteadOfUid) { + $elementValue = $fileReference->getOriginalResource()->getCombinedIdentifier(); + } else { + $elementValue = $fileReference->getOriginalResource()->getProperty('uid_local'); + } + + return $elementValue; + } +} diff --git a/Classes/Domain/Model/Exception.php b/Classes/Domain/Model/Exception.php new file mode 100644 index 0000000..ac158ee --- /dev/null +++ b/Classes/Domain/Model/Exception.php @@ -0,0 +1,25 @@ +addPage($page); + * + * $element1 = GeneralUtility::makeInstance(GenericFormElement::class, 'title', 'Textfield'); # the second argument is the type of the form element + * $page1->addElement($element1); + * \--- + * + * Creating a Form, Using Abstract Form Element Types + * ===================================================== + * + * While you can use the {@link FormDefinition::addPage} or {@link Page::addElement} + * methods and create the Page and FormElement objects manually, it is often better + * to use the corresponding create* methods ({@link FormDefinition::createPage} + * and {@link Page::createElement}), as you pass them an abstract *Form Element Type* + * such as *Text* or *Page*, and the system **automatically + * resolves the implementation class name and sets default values**. + * + * So the simple example from above should be rewritten as follows: + * + * /---code php + * $prototypeConfiguration = []; // We'll talk about this later + * + * $formDefinition = GeneralUtility::makeInstance(FormDefinition::class, 'myForm', $prototypeConfiguration); + * $page1 = $formDefinition->createPage('page1'); + * $element1 = $page1->addElement('title', 'Textfield'); + * \--- + * + * Now, you might wonder how the system knows that the element *Textfield* + * is implemented using a GenericFormElement: **This is configured in the $prototypeConfiguration**. + * + * To make the example from above actually work, we need to add some sensible + * values to *$prototypeConfiguration*: + * + *
+ * $prototypeConfiguration = [
+ *   'formElementsDefinition' => [
+ *     'Page' => [
+ *       'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page'
+ *     ],
+ *     'Textfield' => [
+ *       'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement'
+ *     ]
+ *   ]
+ * ]
+ * 
+ * + * For each abstract *Form Element Type* we add some configuration; in the above + * case only the *implementation class name*. Still, it is possible to set defaults + * for *all* configuration options of such an element, as the following example + * shows: + * + *
+ * $prototypeConfiguration = [
+ *   'formElementsDefinition' => [
+ *     'Page' => [
+ *       'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page',
+ *       'label' => 'this is the label of the page if nothing is specified'
+ *     ],
+ *     'Textfield' => [
+ *       'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement',
+ *       'label' = >'Default Label',
+ *       'defaultValue' => 'Default form element value',
+ *       'properties' => [
+ *         'placeholder' => 'Text which is shown if element is empty'
+ *       ]
+ *     ]
+ *   ]
+ * ]
+ * 
+ * + * Using Preconfigured $prototypeConfiguration + * --------------------------------- + * + * Often, it is not really useful to manually create the $prototypeConfiguration array. + * + * Most of it comes pre-configured inside the YAML settings of the extensions, + * and the {@link \TYPO3\CMS\Form\Domain\Configuration\ConfigurationService} contains helper methods + * which return the ready-to-use *$prototypeConfiguration*. + * + * Property Mapping and Validation Rules + * ===================================== + * + * Besides Pages and FormElements, the FormDefinition can contain information + * about the *format of the data* which is inputted into the form. This generally means: + * + * - expected Data Types + * - Property Mapping Configuration to be used + * - Validation Rules which should apply + * + * Background Info + * --------------- + * You might wonder why Data Types and Validation Rules are *not attached + * to each FormElement itself*. + * + * If the form should create a *hierarchical output structure* such as a multi- + * dimensional array or a PHP object, your expected data structure might look as follows: + *
+ * - person
+ * -- firstName
+ * -- lastName
+ * -- address
+ * --- street
+ * --- city
+ * 
+ * + * Now, let's imagine you want to edit *person.address.street* and *person.address.city*, + * but want to validate that the *combination* of *street* and *city* is valid + * according to some address database. + * + * In this case, the form elements would be configured to fill *street* and *city*, + * but the *validator* needs to be attached to the *compound object* *address*, + * as both parts need to be validated together. + * + * Connecting FormElements to the output data structure + * ==================================================== + * + * The *identifier* of the *FormElement* is most important, as it determines + * where in the output structure the value which is entered by the user is placed, + * and thus also determines which validation rules need to apply. + * + * Using the above example, if you want to create a FormElement for the *street*, + * you should use the identifier *person.address.street*. + * + * Rendering a FormDefinition + * ========================== + * + * In order to trigger *rendering* on a FormDefinition, + * the current {@link \TYPO3\CMS\Extbase\Mvc\Request} needs to be bound to the FormDefinition, + * resulting in a {@link \TYPO3\CMS\Form\Domain\Runtime\FormRuntime} object which contains the *Runtime State* of the form + * (such as the currently inserted values). + * + * /---code php + * # $currentRequest and $currentResponse need to be available, f.e. inside a controller you would + * # use $this->request. Inside a ViewHelper you would use $this->renderingContext->getRequest() + * $form = $formDefinition->bind($currentRequest); + * + * # now, you can use the $form object to get information about the currently + * # entered values into the form, etc. + * \--- + * + * Refer to the {@link \TYPO3\CMS\Form\Domain\Runtime\FormRuntime} API doc for further information. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * + * @internal May change any time, use FormFactoryInterface to select a different FormDefinition if needed + * @todo: Declare final in v12 + */ +class FormDefinition extends AbstractCompositeRenderable implements VariableRenderableInterface +{ + /** + * The Form's pages + * + * @var array + */ + protected $renderables = []; + + /** + * The finishers for this form + * + * @var list + */ + protected array $finishers = []; + + /** + * Property Mapping Rules, indexed by element identifier + * + * @var array + */ + protected array $processingRules = []; + + /** + * Contains all elements of the form, indexed by identifier. + * Is used as internal cache as we need this really often. + * + * @var array + */ + protected array $elementsByIdentifier = []; + + /** + * Form element default values in the format ['elementIdentifier' => 'default value'] + * + * @var array + */ + protected array $elementDefaultValues = []; + + /** + * Renderer class name to be used. + */ + protected string $rendererClassName = ''; + + /** + * @var array> + */ + protected array $typeDefinitions = []; + + /** + * @var array> + */ + protected array $validatorsDefinition = []; + + /** + * @var array> + */ + protected array $finishersDefinition = []; + + /** + * The persistence identifier of the form + */ + protected string $persistenceIdentifier = ''; + + /** + * Constructor. Creates a new FormDefinition with the given identifier. + * + * @param string $identifier The Form Definition's identifier, must be a non-empty string. + * @param array $prototypeConfiguration overrides form defaults of this definition + * @param string $type element type of this form + * @param string|null $persistenceIdentifier the persistence identifier of the form + * @throws IdentifierNotValidException if the identifier was not valid + */ + public function __construct( + string $identifier, + array $prototypeConfiguration = [], + string $type = 'Form', + ?string $persistenceIdentifier = null + ) { + $this->typeDefinitions = $prototypeConfiguration['formElementsDefinition'] ?? []; + $this->validatorsDefinition = $prototypeConfiguration['validatorsDefinition'] ?? []; + $this->finishersDefinition = $prototypeConfiguration['finishersDefinition'] ?? []; + + if ($identifier === '') { + throw new IdentifierNotValidException('The given identifier was empty.', 1477082503); + } + + $this->identifier = $identifier; + $this->type = $type; + $this->persistenceIdentifier = (string)$persistenceIdentifier; + + if ($prototypeConfiguration !== []) { + $this->initializeFromFormDefaults(); + } + } + + /** + * Initialize the form defaults of the current type + * + * @throws TypeDefinitionNotFoundException + * @internal + */ + protected function initializeFromFormDefaults() + { + if (!isset($this->typeDefinitions[$this->type])) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $this->type), 1474905835); + } + $typeDefinition = $this->typeDefinitions[$this->type]; + $this->setOptions($typeDefinition); + } + + /** + * Set multiple properties of this object at once. + * Every property which has a corresponding set* method can be set using + * the passed $options array. + * + * @internal + */ + public function setOptions(array $options, bool $resetFinishers = false) + { + if (isset($options['rendererClassName'])) { + $this->setRendererClassName($options['rendererClassName']); + } + if (isset($options['label'])) { + $this->setLabel($options['label']); + } + if (isset($options['renderingOptions'])) { + foreach ($options['renderingOptions'] as $key => $value) { + $this->setRenderingOption($key, $value); + } + } + if (isset($options['finishers'])) { + if ($resetFinishers) { + $this->finishers = []; + } + foreach ($options['finishers'] as $finisherConfiguration) { + $this->createFinisher($finisherConfiguration['identifier'], $finisherConfiguration['options'] ?? []); + } + } + + if (isset($options['variants'])) { + foreach ($options['variants'] as $variantConfiguration) { + $this->createVariant($variantConfiguration); + } + } + + ArrayUtility::assertAllArrayKeysAreValid( + $options, + ['rendererClassName', 'renderingOptions', 'finishers', 'formEditor', 'label', 'variants'] + ); + } + + /** + * Create a page with the given $identifier and attach this page to the form. + * + * - Create Page object based on the given $typeName + * - set defaults inside the Page object + * - attach Page object to this form + * - return the newly created Page object + * + * @param string $identifier Identifier of the new page + * @param string $typeName Type of the new page + * @return Page the newly created page + * @throws TypeDefinitionNotFoundException + */ + public function createPage(string $identifier, string $typeName = 'Page'): Page + { + if (!isset($this->typeDefinitions[$typeName])) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $typeName), 1474905953); + } + + $typeDefinition = $this->typeDefinitions[$typeName]; + + if (!isset($typeDefinition['implementationClassName'])) { + throw new TypeDefinitionNotFoundException(sprintf('The "implementationClassName" was not set in type definition "%s".', $typeName), 1477083126); + } + $implementationClassName = $typeDefinition['implementationClassName']; + + /** @var Page $page */ + $page = GeneralUtility::makeInstance($implementationClassName, $identifier, $typeName); + + if (isset($typeDefinition['label'])) { + $page->setLabel($typeDefinition['label']); + } + + if (isset($typeDefinition['renderingOptions'])) { + foreach ($typeDefinition['renderingOptions'] as $key => $value) { + $page->setRenderingOption($key, $value); + } + } + + if (isset($typeDefinition['variants'])) { + foreach ($typeDefinition['variants'] as $variantConfiguration) { + $page->createVariant($variantConfiguration); + } + } + + ArrayUtility::assertAllArrayKeysAreValid( + $typeDefinition, + ['implementationClassName', 'label', 'renderingOptions', 'formEditor', 'variants'] + ); + + $this->addPage($page); + return $page; + } + + /** + * Add a new page at the end of the form. + * + * Instead of this method, you should often use {@link createPage} instead. + * + * @param Page $page + * @throws FormDefinitionConsistencyException if Page is already added to a FormDefinition + * @see createPage + */ + public function addPage(Page $page) + { + $this->addRenderable($page); + } + + /** + * Get the Form's pages + * + * @return array The Form's pages in the correct order + */ + public function getPages(): array + { + return $this->renderables; + } + + /** + * Check whether a page with the given $index exists + * + * @return bool TRUE if a page with the given $index exists, otherwise FALSE + */ + public function hasPageWithIndex(int $index): bool + { + return isset($this->renderables[$index]); + } + + /** + * Get the page with the passed index. The first page has index zero. + * + * If page at $index does not exist, an exception is thrown. @see hasPageWithIndex() + * + * @param int $index + * @return Page the page + * @throws FormException if the specified index does not exist + */ + public function getPageByIndex(int $index) + { + if (!$this->hasPageWithIndex($index)) { + throw new FormException(sprintf('There is no page with an index of %d', $index), 1329233627); + } + return $this->renderables[$index]; + } + + /** + * Adds the specified finisher to this form + */ + public function addFinisher(FinisherInterface $finisher) + { + $this->finishers[] = $finisher; + } + + /** + * @param string $finisherIdentifier identifier of the finisher as registered in the current form (for example: "Redirect") + * @param array $options options for this finisher in the format ['option1' => 'value1', 'option2' => 'value2', ...] + * @throws FinisherPresetNotFoundException + */ + public function createFinisher(string $finisherIdentifier, array $options = []): FinisherInterface + { + if (isset($this->finishersDefinition[$finisherIdentifier]['implementationClassName'])) { + $implementationClassName = $this->finishersDefinition[$finisherIdentifier]['implementationClassName']; + $defaultOptions = $this->finishersDefinition[$finisherIdentifier]['options'] ?? []; + ArrayUtility::mergeRecursiveWithOverrule($defaultOptions, $options); + /** @var FinisherInterface $finisher */ + $finisher = GeneralUtility::makeInstance($implementationClassName); + $finisher->setFinisherIdentifier($finisherIdentifier); + $finisher->setOptions($defaultOptions); + $this->addFinisher($finisher); + return $finisher; + } + throw new FinisherPresetNotFoundException('The finisher preset identified by "' . $finisherIdentifier . '" could not be found, or the implementationClassName was not specified.', 1328709784); + } + + /** + * Gets all finishers of this form + * + * @return list + */ + public function getFinishers(): array + { + return $this->finishers; + } + + /** + * Add an element to the ElementsByIdentifier Cache. + * + * @throws DuplicateFormElementException + * @internal + */ + public function registerRenderable(RenderableInterface $renderable) + { + if ($renderable instanceof FormElementInterface) { + if (isset($this->elementsByIdentifier[$renderable->getIdentifier()])) { + throw new DuplicateFormElementException(sprintf('A form element with identifier "%s" is already part of the form.', $renderable->getIdentifier()), 1325663761); + } + $this->elementsByIdentifier[$renderable->getIdentifier()] = $renderable; + } + } + + /** + * Remove an element from the ElementsByIdentifier cache + * + * @internal + */ + public function unregisterRenderable(RenderableInterface $renderable) + { + if ($renderable instanceof FormElementInterface) { + unset($this->elementsByIdentifier[$renderable->getIdentifier()]); + } + } + + /** + * Get all form elements with their identifiers as keys + * + * @return array + */ + public function getElements(): array + { + return $this->elementsByIdentifier; + } + + /** + * Get a Form Element by its identifier + * + * If identifier does not exist, returns NULL. + * + * @param string $elementIdentifier + * @return FormElementInterface|null The element with the given $elementIdentifier or NULL if none found + */ + public function getElementByIdentifier(string $elementIdentifier) + { + return $this->elementsByIdentifier[$elementIdentifier] ?? null; + } + + /** + * Sets the default value of a form element + * + * @param string $elementIdentifier identifier of the form element. This supports property paths! + * @param mixed $defaultValue + * @internal + */ + public function addElementDefaultValue(string $elementIdentifier, $defaultValue) + { + $this->elementDefaultValues = ArrayUtility::setValueByPath( + $this->elementDefaultValues, + $elementIdentifier, + $defaultValue, + '.' + ); + } + + /** + * returns the default value of the specified form element + * or NULL if no default value was set + * + * @param string $elementIdentifier identifier of the form element. This supports property paths! + * @return mixed The elements default value + * @internal + */ + public function getElementDefaultValueByIdentifier(string $elementIdentifier) + { + return ObjectAccess::getPropertyPath($this->elementDefaultValues, $elementIdentifier); + } + + /** + * Move $pageToMove before $referencePage + */ + public function movePageBefore(Page $pageToMove, Page $referencePage) + { + $this->moveRenderableBefore($pageToMove, $referencePage); + } + + /** + * Move $pageToMove after $referencePage + */ + public function movePageAfter(Page $pageToMove, Page $referencePage) + { + $this->moveRenderableAfter($pageToMove, $referencePage); + } + + /** + * Remove $pageToRemove from form + */ + public function removePage(Page $pageToRemove) + { + $this->removeRenderable($pageToRemove); + } + + /** + * Bind the current request & response to this form instance, effectively creating + * a new "instance" of the Form. + */ + public function bind(RequestInterface $request): FormRuntime + { + $formRuntime = GeneralUtility::makeInstance(FormRuntime::class); + $formRuntime->setFormDefinition($this); + $formRuntime->setRequest($request); + $formRuntime->initialize(); + return $formRuntime; + } + + public function getProcessingRule(string $propertyPath): ProcessingRule + { + if (!isset($this->processingRules[$propertyPath])) { + $this->processingRules[$propertyPath] = GeneralUtility::makeInstance(ProcessingRule::class); + } + return $this->processingRules[$propertyPath]; + } + + /** + * Get all mapping rules + * + * @return array + * @internal + */ + public function getProcessingRules(): array + { + return $this->processingRules; + } + + /** + * @return array> + * @internal + */ + public function getTypeDefinitions(): array + { + return $this->typeDefinitions; + } + + /** + * @return array> + * @internal + */ + public function getValidatorsDefinition(): array + { + return $this->validatorsDefinition; + } + + /** + * Get the persistence identifier of the form + * + * @internal + */ + public function getPersistenceIdentifier(): string + { + return $this->persistenceIdentifier; + } + + /** + * Set the renderer class name + */ + public function setRendererClassName(string $rendererClassName) + { + $this->rendererClassName = $rendererClassName; + } + + /** + * Get the classname of the renderer + */ + public function getRendererClassName(): string + { + return $this->rendererClassName; + } +} diff --git a/Classes/Domain/Model/FormElements/AbstractFormElement.php b/Classes/Domain/Model/FormElements/AbstractFormElement.php new file mode 100644 index 0000000..18318aa --- /dev/null +++ b/Classes/Domain/Model/FormElements/AbstractFormElement.php @@ -0,0 +1,166 @@ +identifier = $identifier; + $this->type = $type; + } + + /** + * Override this method in your custom FormElements if needed + */ + public function initializeFormElement() {} + + /** + * Get the global unique identifier of the element + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + $uniqueIdentifier = sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + $uniqueIdentifier = (string)preg_replace('/[^a-zA-Z0-9_-]/', '_', $uniqueIdentifier); + return lcfirst($uniqueIdentifier); + } + + public function setOptions(array $options, bool $resetValidators = false) + { + if (isset($options['defaultValue'])) { + $this->setDefaultValue($options['defaultValue']); + } + + if (isset($options['properties'])) { + foreach ($options['properties'] as $key => $value) { + $this->setProperty($key, $value); + } + } + + parent::setOptions($options, $resetValidators); + } + + /** + * Get the default value of the element + * + * @return mixed + */ + public function getDefaultValue() + { + $formDefinition = $this->getRootForm(); + return $formDefinition->getElementDefaultValueByIdentifier($this->identifier); + } + + /** + * Set the default value of the element + * + * @param mixed $defaultValue + */ + public function setDefaultValue($defaultValue) + { + $formDefinition = $this->getRootForm(); + $currentDefaultValue = $formDefinition->getElementDefaultValueByIdentifier($this->identifier); + if (is_array($currentDefaultValue) && is_array($defaultValue)) { + ArrayUtility::mergeRecursiveWithOverrule($currentDefaultValue, $defaultValue); + $defaultValue = ArrayUtility::removeNullValuesRecursive($currentDefaultValue); + } + $formDefinition->addElementDefaultValue($this->identifier, $defaultValue); + } + + /** + * Check if the element is required + */ + public function isRequired(): bool + { + foreach ($this->getValidators() as $validator) { + if ($validator instanceof NotEmptyValidator) { + return true; + } + } + return false; + } + + /** + * Set a property of the element + * + * @param mixed $value + */ + public function setProperty(string $key, $value) + { + if (is_array($value) && isset($this->properties[$key]) && is_array($this->properties[$key])) { + ArrayUtility::mergeRecursiveWithOverrule($this->properties[$key], $value); + $this->properties[$key] = ArrayUtility::removeNullValuesRecursive($this->properties[$key]); + } elseif ($value === null) { + unset($this->properties[$key]); + } else { + $this->properties[$key] = $value; + } + } + + /** + * Get all properties + */ + public function getProperties(): array + { + return $this->properties; + } +} diff --git a/Classes/Domain/Model/FormElements/AbstractSection.php b/Classes/Domain/Model/FormElements/AbstractSection.php new file mode 100644 index 0000000..e28ebf4 --- /dev/null +++ b/Classes/Domain/Model/FormElements/AbstractSection.php @@ -0,0 +1,182 @@ +identifier = $identifier; + $this->type = $type; + } + + /** + * Get the child Form Elements + * + * @return FormElementInterface[] The Page's elements + */ + public function getElements(): array + { + return $this->renderables; + } + + /** + * Get the child Form Elements + * + * @return FormElementInterface[] The Page's elements + */ + public function getElementsRecursively(): array + { + return $this->getRenderablesRecursively(); + } + + /** + * Add a new form element at the end of the section + * + * @param FormElementInterface $formElement The form element to add + * @throws FormDefinitionConsistencyException if FormElement is already added to a section + */ + public function addElement(FormElementInterface $formElement) + { + $this->addRenderable($formElement); + } + + /** + * Create a form element with the given $identifier and attach it to this section/page. + * + * - Create Form Element object based on the given $typeName + * - set defaults inside the Form Element (based on the parent form's field defaults) + * - attach Form Element to this Section/Page + * - return the newly created Form Element object + * + * + * @param string $identifier Identifier of the new form element + * @param string $typeName type of the new form element + * @return FormElementInterface the newly created form element + * @throws TypeDefinitionNotFoundException + * @throws TypeDefinitionNotValidException + */ + public function createElement(string $identifier, string $typeName): FormElementInterface + { + $formDefinition = $this->getRootForm(); + + $typeDefinitions = $formDefinition->getTypeDefinitions(); + if (isset($typeDefinitions[$typeName])) { + $typeDefinition = $typeDefinitions[$typeName]; + } else { + $renderingOptions = $formDefinition->getRenderingOptions(); + $skipUnknownElements = isset($renderingOptions['skipUnknownElements']) && $renderingOptions['skipUnknownElements'] === true; + if (!$skipUnknownElements) { + throw new TypeDefinitionNotFoundException(sprintf('Type "%s" not found. Probably some configuration is missing.', $typeName), 1382364019); + } + + $element = GeneralUtility::makeInstance(UnknownFormElement::class, $identifier, $typeName); + $this->addElement($element); + return $element; + } + + if (!isset($typeDefinition['implementationClassName'])) { + throw new TypeDefinitionNotFoundException(sprintf('The "implementationClassName" was not set in type definition "%s".', $typeName), 1325689855); + } + + $implementationClassName = $typeDefinition['implementationClassName']; + $element = GeneralUtility::makeInstance($implementationClassName, $identifier, $typeName); + if (!$element instanceof FormElementInterface) { + throw new TypeDefinitionNotValidException(sprintf('The "implementationClassName" for element "%s" ("%s") does not implement the FormElementInterface.', $identifier, $implementationClassName), 1327318156); + } + unset($typeDefinition['implementationClassName']); + + $this->addElement($element); + $element->setOptions($typeDefinition); + + $element->initializeFormElement(); + return $element; + } + + /** + * Move FormElement $element before $referenceElement. + * + * Both $element and $referenceElement must be direct descendants of this Section/Page. + * + * @param FormElementInterface $elementToMove + * @param FormElementInterface $referenceElement + */ + public function moveElementBefore(FormElementInterface $elementToMove, FormElementInterface $referenceElement) + { + $this->moveRenderableBefore($elementToMove, $referenceElement); + } + + /** + * Move FormElement $element after $referenceElement + * + * Both $element and $referenceElement must be direct descendants of this Section/Page. + * + * @param FormElementInterface $elementToMove + * @param FormElementInterface $referenceElement + */ + public function moveElementAfter(FormElementInterface $elementToMove, FormElementInterface $referenceElement) + { + $this->moveRenderableAfter($elementToMove, $referenceElement); + } + + /** + * Remove $elementToRemove from this Section/Page + */ + public function removeElement(FormElementInterface $elementToRemove) + { + $this->removeRenderable($elementToRemove); + } +} diff --git a/Classes/Domain/Model/FormElements/Date.php b/Classes/Domain/Model/FormElements/Date.php new file mode 100644 index 0000000..5e1d0d2 --- /dev/null +++ b/Classes/Domain/Model/FormElements/Date.php @@ -0,0 +1,56 @@ +setDataType(\DateTime::class); + /** @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration */ + $propertyMappingConfiguration = $this->getRootForm()->getProcessingRule($this->getIdentifier())->getPropertyMappingConfiguration(); + // @see https://www.w3.org/TR/2011/WD-html-markup-20110405/input.date.html#input.date.attrs.value + // 'Y-m-d' = https://tools.ietf.org/html/rfc3339#section-5.6 -> full-date + $propertyMappingConfiguration->setTypeConverterOption(DateTimeConverter::class, DateTimeConverter::CONFIGURATION_DATE_FORMAT, 'Y-m-d'); + } + + /** + * @param \DateTime $value + */ + public function valueToString($value): string + { + $dateFormat = $this->properties['displayFormat'] ?? 'Y-m-d'; + + return $value->format($dateFormat); + } +} diff --git a/Classes/Domain/Model/FormElements/FileUpload.php b/Classes/Domain/Model/FormElements/FileUpload.php new file mode 100644 index 0000000..71ac8e3 --- /dev/null +++ b/Classes/Domain/Model/FormElements/FileUpload.php @@ -0,0 +1,107 @@ +setDataType(FileReference::class); + + // Set the property mapping configuration for the file upload element. + // * Add the UploadedFileReferenceConverter to convert an uploaded file to a + // FileReference (single upload) or ObjectStorage (multiple uploads). + // * Setup the storage: + // If the property "saveToFileMount" exist for this element it will be used. + // If this file mount or the property "saveToFileMount" does not exist + // the default storage "1:/user_uploads/" will be used. Uploads are placed + // in a dedicated sub-folder (e.g. ".../form_<40-chars-hash>/actual.file"). + $typeConverter = GeneralUtility::makeInstance(UploadedFileReferenceConverter::class); + /** @var \TYPO3\CMS\Extbase\Property\PropertyMappingConfiguration $propertyMappingConfiguration */ + $propertyMappingConfiguration = $this->getRootForm() + ->getProcessingRule($this->getIdentifier()) + ->getPropertyMappingConfiguration() + ->setTypeConverter($typeConverter); + + $uploadConfiguration = [ + UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_CONFLICT_MODE => 'rename', + ]; + + // In preview mode (Form Editor backend module), skip upload folder resolution + // entirely. File uploads are non-functional during preview and resolving the + // target folder may throw access permission exceptions for backend users who + // do not have access to the configured upload storage. + if (!($this->getRootForm()->getRenderingOptions()['previewMode'] ?? false)) { + $saveToFileMountIdentifier = $this->getProperties()['saveToFileMount'] ?? ''; + if ($this->checkSaveFileMountAccess($saveToFileMountIdentifier)) { + $uploadConfiguration[UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_FOLDER] = $saveToFileMountIdentifier; + } else { + // @todo Why should uploaded files be stored to the same directory as the *.form.yaml definitions? + $persistenceIdentifier = $this->getRootForm()->getPersistenceIdentifier(); + if (!empty($persistenceIdentifier)) { + $pathinfo = PathUtility::pathinfo($persistenceIdentifier); + $saveToFileMountIdentifier = $pathinfo['dirname']; + if ($this->checkSaveFileMountAccess($saveToFileMountIdentifier)) { + $uploadConfiguration[UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_FOLDER] = $saveToFileMountIdentifier; + } + } + } + } + $propertyMappingConfiguration->setTypeConverterOptions(UploadedFileReferenceConverter::class, $uploadConfiguration); + } + + /** + * @internal + */ + protected function checkSaveFileMountAccess(string $saveToFileMountIdentifier): bool + { + if (empty($saveToFileMountIdentifier)) { + return false; + } + + if (PathUtility::isExtensionPath($saveToFileMountIdentifier)) { + return false; + } + + $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); + + try { + $resourceFactory->getFolderObjectFromCombinedIdentifier($saveToFileMountIdentifier); + return true; + } catch (\InvalidArgumentException|InsufficientFolderAccessPermissionsException|FolderDoesNotExistException $e) { + return false; + } + } +} diff --git a/Classes/Domain/Model/FormElements/FormElementInterface.php b/Classes/Domain/Model/FormElements/FormElementInterface.php new file mode 100644 index 0000000..0b7e672 --- /dev/null +++ b/Classes/Domain/Model/FormElements/FormElementInterface.php @@ -0,0 +1,117 @@ + + * @internal + */ + public function getValidators(): \SplObjectStorage; + + /** + * Registers a validator for this element + */ + public function addValidator(ValidatorInterface $validator); + + /** + * Set the target data type for this element + * + * @param string $dataType the target data type + */ + public function setDataType(string $dataType); + + /** + * Whether or not this element is required + */ + public function isRequired(): bool; +} diff --git a/Classes/Domain/Model/FormElements/GenericFormElement.php b/Classes/Domain/Model/FormElements/GenericFormElement.php new file mode 100644 index 0000000..0e31dac --- /dev/null +++ b/Classes/Domain/Model/FormElements/GenericFormElement.php @@ -0,0 +1,29 @@ + $value) { + $this->setProperty($key, $value); + } + } + + parent::setOptions($options, $resetValidators); + } + + /** + * Returns a unique identifier of this element. + * While element identifiers are only unique within one form, + * this includes the identifier of the form itself, making it "globally" unique + * + * @return string the "globally" unique identifier of this element + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + return sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + } + + /** + * Get the default value with which the Form Element should be initialized + * during display. + * Note: This is currently not used for section elements + * + * @return mixed the default value for this Form Element + */ + public function getDefaultValue() + { + return null; + } + + /** + * Set the default value with which the Form Element should be initialized + * during display. + * Note: This is currently ignored for section elements + * + * @param mixed $defaultValue the default value for this Form Element + */ + public function setDefaultValue($defaultValue) {} + + /** + * Get all element-specific configuration properties + */ + public function getProperties(): array + { + return $this->properties; + } + + /** + * Set an element-specific configuration property. + * + * @param mixed $value + */ + public function setProperty(string $key, $value) + { + if (is_array($value) && isset($this->properties[$key]) && is_array($this->properties[$key])) { + ArrayUtility::mergeRecursiveWithOverrule($this->properties[$key], $value); + $this->properties[$key] = ArrayUtility::removeNullValuesRecursive($this->properties[$key]); + } elseif ($value === null) { + unset($this->properties[$key]); + } else { + $this->properties[$key] = $value; + } + } + + /** + * Whether or not this element is required + */ + public function isRequired(): bool + { + foreach ($this->getValidators() as $validator) { + if ($validator instanceof NotEmptyValidator) { + return true; + } + } + return false; + } +} diff --git a/Classes/Domain/Model/FormElements/StringableFormElementInterface.php b/Classes/Domain/Model/FormElements/StringableFormElementInterface.php new file mode 100644 index 0000000..7b63ac8 --- /dev/null +++ b/Classes/Domain/Model/FormElements/StringableFormElementInterface.php @@ -0,0 +1,32 @@ +identifier = $identifier; + $this->type = $type; + } + + /** + * Sets up the form element + */ + public function initializeFormElement() {} + + /** + * Returns a unique identifier of this element. + * While element identifiers are only unique within one form, + * this includes the identifier of the form itself, making it "globally" unique + * + * @return string the "globally" unique identifier of this element + */ + public function getUniqueIdentifier(): string + { + $formDefinition = $this->getRootForm(); + $uniqueIdentifier = sprintf('%s-%s', $formDefinition->getIdentifier(), $this->identifier); + $uniqueIdentifier = (string)preg_replace('/[^a-zA-Z0-9-_]/', '_', $uniqueIdentifier); + return lcfirst($uniqueIdentifier); + } + + /** + * Get the template name of the renderable + */ + public function getTemplateName(): string + { + return 'UnknownElement'; + } + + /** + * @return mixed the default value for this Form Element + * @internal + */ + public function getDefaultValue() + { + return null; + } + + /** + * Not used in this implementation + * + * @param mixed $defaultValue the default value for this Form Element + * @internal + */ + public function setDefaultValue($defaultValue) {} + + /** + * Not used in this implementation + * + * @param mixed $value + * @internal + */ + public function setProperty(string $key, $value) {} + + /** + * @internal + */ + public function getProperties(): array + { + return []; + } + + /** + * @internal + */ + public function isRequired(): bool + { + return false; + } +} diff --git a/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php b/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php new file mode 100644 index 0000000..90585fc --- /dev/null +++ b/Classes/Domain/Model/Renderable/AbstractCompositeRenderable.php @@ -0,0 +1,209 @@ +getParentRenderable() !== null) { + throw new FormDefinitionConsistencyException(sprintf('The renderable with identifier "%s" is already added to another element (element identifier: "%s").', $renderable->getIdentifier(), $renderable->getParentRenderable()->getIdentifier()), 1325665144); + } + $renderable->setIndex(count($this->renderables)); + $renderable->setParentRenderable($this); + $this->renderables[] = $renderable; + } + + /** + * Move $renderableToMove before $referenceRenderable + * + * This function will be wrapped by the subclasses, f.e. with an "movePageBefore" + * or "moveElementBefore" method with the correct type hint. + * + * @param RenderableInterface $renderableToMove + * @param RenderableInterface $referenceRenderable + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function moveRenderableBefore(RenderableInterface $renderableToMove, RenderableInterface $referenceRenderable) + { + if ($renderableToMove->getParentRenderable() !== $referenceRenderable->getParentRenderable() || $renderableToMove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('Moved renderables need to be part of the same parent element.', 1326089744); + } + + $reorderedRenderables = []; + $i = 0; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToMove) { + continue; + } + + if ($renderable === $referenceRenderable) { + $reorderedRenderables[] = $renderableToMove; + $renderableToMove->setIndex($i); + $i++; + } + $reorderedRenderables[] = $renderable; + $renderable->setIndex($i); + $i++; + } + $this->renderables = $reorderedRenderables; + } + + /** + * Move $renderableToMove after $referenceRenderable + * + * This function will be wrapped by the subclasses, f.e. with an "movePageAfter" + * or "moveElementAfter" method with the correct type hint. + * + * @param RenderableInterface $renderableToMove + * @param RenderableInterface $referenceRenderable + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function moveRenderableAfter(RenderableInterface $renderableToMove, RenderableInterface $referenceRenderable) + { + if ($renderableToMove->getParentRenderable() !== $referenceRenderable->getParentRenderable() || $renderableToMove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('Moved renderables need to be part of the same parent element.', 1477083145); + } + + $reorderedRenderables = []; + $i = 0; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToMove) { + continue; + } + + $reorderedRenderables[] = $renderable; + $renderable->setIndex($i); + $i++; + + if ($renderable === $referenceRenderable) { + $reorderedRenderables[] = $renderableToMove; + $renderableToMove->setIndex($i); + $i++; + } + } + $this->renderables = $reorderedRenderables; + } + + /** + * Returns all RenderableInterface instances of this composite renderable recursively + * + * @return RenderableInterface[] + * @internal + */ + public function getRenderablesRecursively(): array + { + $renderables = []; + foreach ($this->renderables as $renderable) { + $renderables[] = $renderable; + if ($renderable instanceof CompositeRenderableInterface) { + $renderables = array_merge($renderables, $renderable->getRenderablesRecursively()); + } + } + return $renderables; + } + + /** + * Remove a renderable from this renderable. + * + * This function will be wrapped by the subclasses, f.e. with an "removePage" + * or "removeElement" method with the correct type hint. + * + * @param RenderableInterface $renderableToRemove + * @throws FormDefinitionConsistencyException + * @internal + */ + protected function removeRenderable(RenderableInterface $renderableToRemove) + { + if ($renderableToRemove->getParentRenderable() !== $this) { + throw new FormDefinitionConsistencyException('The renderable to be removed must be part of the calling parent renderable.', 1326090127); + } + + $updatedRenderables = []; + foreach ($this->renderables as $renderable) { + if ($renderable === $renderableToRemove) { + continue; + } + + $updatedRenderables[] = $renderable; + } + $this->renderables = $updatedRenderables; + + $renderableToRemove->onRemoveFromParentRenderable(); + } + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @internal + */ + public function registerInFormIfPossible() + { + parent::registerInFormIfPossible(); + foreach ($this->renderables as $renderable) { + $renderable->registerInFormIfPossible(); + } + } + + /** + * This function is called after a renderable has been removed from its parent + * renderable. + * This just passes the event down to all child renderables of this composite renderable. + * + * @internal + */ + public function onRemoveFromParentRenderable() + { + foreach ($this->renderables as $renderable) { + $renderable->onRemoveFromParentRenderable(); + } + parent::onRemoveFromParentRenderable(); + } +} diff --git a/Classes/Domain/Model/Renderable/AbstractRenderable.php b/Classes/Domain/Model/Renderable/AbstractRenderable.php new file mode 100644 index 0000000..08a95e4 --- /dev/null +++ b/Classes/Domain/Model/Renderable/AbstractRenderable.php @@ -0,0 +1,448 @@ +type; + } + + /** + * Get the identifier of the element + */ + public function getIdentifier(): string + { + return $this->identifier; + } + + /** + * Set the identifier of the element + */ + public function setIdentifier(string $identifier) + { + $this->identifier = $identifier; + } + + public function getRequest(): ?ServerRequestInterface + { + return $this->request; + } + + public function setRequest(?ServerRequestInterface $request): void + { + $this->request = $request; + } + + /** + * Set multiple properties of this object at once. + * Every property which has a corresponding set* method can be set using + * the passed $options array. + */ + public function setOptions(array $options, bool $resetValidators = false) + { + if (isset($options['label'])) { + $this->setLabel($options['label']); + } + + if (isset($options['renderingOptions'])) { + foreach ($options['renderingOptions'] as $key => $value) { + $this->setRenderingOption($key, $value); + } + } + + if (isset($options['validators'])) { + $runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime'); + $configurationHashes = $runtimeCache->get('formAbstractRenderableConfigurationHashes') ?: []; + + if ($resetValidators) { + $this->getRootForm()->getProcessingRule($this->getIdentifier())->removeAllValidators(); + $configurationHashes = []; + } + + foreach ($options['validators'] as $validatorConfiguration) { + $configurationHash = md5( + spl_object_hash($this) + . json_encode($validatorConfiguration) + ); + if (in_array($configurationHash, $configurationHashes)) { + continue; + } + $this->createValidator($validatorConfiguration['identifier'], $validatorConfiguration['options'] ?? []); + $configurationHashes[] = $configurationHash; + $runtimeCache->set('formAbstractRenderableConfigurationHashes', $configurationHashes); + } + } + + if (isset($options['variants'])) { + foreach ($options['variants'] as $variantConfiguration) { + $this->createVariant($variantConfiguration); + } + } + + ArrayUtility::assertAllArrayKeysAreValid( + $options, + ['label', 'defaultValue', 'properties', 'renderingOptions', 'validators', 'formEditor', 'variants'] + ); + } + + /** + * Create a validator for the element. + * + * @throws ValidatorPresetNotFoundException + */ + public function createValidator(string $validatorIdentifier, array $options = []): ?ValidatorInterface + { + $validatorsDefinition = $this->getRootForm()->getValidatorsDefinition(); + if (isset($validatorsDefinition[$validatorIdentifier]) && is_array($validatorsDefinition[$validatorIdentifier]) && isset($validatorsDefinition[$validatorIdentifier]['implementationClassName'])) { + $implementationClassName = $validatorsDefinition[$validatorIdentifier]['implementationClassName']; + $defaultOptions = $validatorsDefinition[$validatorIdentifier]['options'] ?? []; + ArrayUtility::mergeRecursiveWithOverrule($defaultOptions, $options); + // @todo: It would be great if Renderable's and FormElements could use DI, but especially + // FormElements which extend AbstractRenderable pollute __construct() with manual + // arguments. To retrieve the ValidatorResolver, we have to fall back to getContainer() + // for now, until this has been resolved. + if ($this->validatorResolver === null) { + $container = GeneralUtility::getContainer(); + $this->validatorResolver = $container->get(ValidatorResolver::class); + } + $validator = $this->validatorResolver->createValidator($implementationClassName, $defaultOptions, $this->request); + if ($validator !== null) { + $this->addValidator($validator); + } + return $validator; + } + throw new ValidatorPresetNotFoundException('The validator preset identified by "' . $validatorIdentifier . '" could not be found, or the implementationClassName was not specified.', 1328710202); + } + + /** + * Add a validator to the element. + */ + public function addValidator(ValidatorInterface $validator) + { + $formDefinition = $this->getRootForm(); + $formDefinition->getProcessingRule($this->getIdentifier())->addValidator($validator); + } + + /** + * Get all validators on the element + * + * @internal + */ + public function getValidators(): \SplObjectStorage + { + $formDefinition = $this->getRootForm(); + return $formDefinition->getProcessingRule($this->getIdentifier())->getValidators(); + } + + /** + * Set the datatype + */ + public function setDataType(string $dataType) + { + $formDefinition = $this->getRootForm(); + $formDefinition->getProcessingRule($this->getIdentifier())->setDataType($dataType); + } + + /** + * Get the classname of the renderer + */ + public function getRendererClassName(): string + { + return $this->getRootForm()->getRendererClassName(); + } + + /** + * Get all rendering options + */ + public function getRenderingOptions(): array + { + return $this->renderingOptions; + } + + /** + * Set the rendering option $key to $value. + * + * @param mixed $value + * @return mixed + */ + public function setRenderingOption(string $key, $value) + { + if (is_array($value) && isset($this->renderingOptions[$key]) && is_array($this->renderingOptions[$key])) { + ArrayUtility::mergeRecursiveWithOverrule($this->renderingOptions[$key], $value); + $this->renderingOptions[$key] = ArrayUtility::removeNullValuesRecursive($this->renderingOptions[$key]); + } elseif ($value === null) { + unset($this->renderingOptions[$key]); + } else { + $this->renderingOptions[$key] = $value; + } + } + + /** + * Get the parent renderable + * + * @return CompositeRenderableInterface|null + */ + public function getParentRenderable() + { + return $this->parentRenderable; + } + + /** + * Set the parent renderable + */ + public function setParentRenderable(CompositeRenderableInterface $parentRenderable) + { + $this->parentRenderable = $parentRenderable; + $this->registerInFormIfPossible(); + } + + /** + * Get the root form this element belongs to + * + * @throws FormDefinitionConsistencyException + */ + public function getRootForm(): FormDefinition + { + $rootRenderable = $this->parentRenderable; + while ($rootRenderable !== null && !($rootRenderable instanceof FormDefinition)) { + $rootRenderable = $rootRenderable->getParentRenderable(); + } + if ($rootRenderable === null) { + throw new FormDefinitionConsistencyException(sprintf('The form element "%s" is not attached to a parent form.', $this->identifier), 1326803398); + } + + return $rootRenderable; + } + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @internal + */ + public function registerInFormIfPossible() + { + try { + $rootForm = $this->getRootForm(); + $rootForm->registerRenderable($this); + } catch (FormDefinitionConsistencyException $exception) { + } + } + + /** + * Triggered when the renderable is removed from it's parent + * + * @internal + */ + public function onRemoveFromParentRenderable() + { + $event = GeneralUtility::makeInstance(EventDispatcherInterface::class)->dispatch( + new BeforeRenderableIsRemovedFromFormEvent($this) + ); + if ($event->isPropagationStopped()) { + return; + } + + try { + $rootForm = $this->getRootForm(); + $rootForm->unregisterRenderable($this); + } catch (FormDefinitionConsistencyException $exception) { + } + $this->parentRenderable = null; + } + + /** + * Get the index of the renderable + * + * @internal + */ + public function getIndex(): int + { + return $this->index; + } + + /** + * Set the index of the renderable + * + * @internal + */ + public function setIndex(int $index) + { + $this->index = $index; + } + + /** + * Get the label of the renderable + */ + public function getLabel(): string + { + return $this->label; + } + + /** + * Set the label which shall be displayed next to the form element + */ + public function setLabel(string $label) + { + $this->label = $label; + } + + /** + * Get the templateName name of the renderable + */ + public function getTemplateName(): string + { + return empty($this->renderingOptions['templateName']) + ? $this->type + : $this->renderingOptions['templateName']; + } + + /** + * Returns whether this renderable is enabled + */ + public function isEnabled(): bool + { + return !isset($this->renderingOptions['enabled']) || (bool)$this->renderingOptions['enabled'] === true; + } + + /** + * Get all rendering variants + * + * @return RenderableVariantInterface[] + */ + public function getVariants(): array + { + return $this->variants; + } + + public function createVariant(array $options): RenderableVariantInterface + { + $identifier = $options['identifier'] ?? ''; + unset($options['identifier']); + + $variant = GeneralUtility::makeInstance(RenderableVariant::class, $identifier, $options, $this); + + $this->addVariant($variant); + return $variant; + } + + /** + * Adds the specified variant to this form element + */ + public function addVariant(RenderableVariantInterface $variant) + { + $this->variants[$variant->getIdentifier()] = $variant; + } + + /** + * Apply the specified variant to this form element + * regardless of their conditions + */ + public function applyVariant(RenderableVariantInterface $variant) + { + $variant->apply(); + } +} diff --git a/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php b/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php new file mode 100644 index 0000000..0f8629d --- /dev/null +++ b/Classes/Domain/Model/Renderable/CompositeRenderableInterface.php @@ -0,0 +1,40 @@ +parentRenderable or deregistering the renderable + * of the form. + * + * @internal + */ + public function onRemoveFromParentRenderable(); + + /** + * Register this element at the parent form, if there is a connection to the parent form. + * + * @internal + */ + public function registerInFormIfPossible(); + + /** + * Get the template name of the renderable + */ + public function getTemplateName(): string; + + /** + * Returns whether this renderable is enabled + */ + public function isEnabled(): bool; +} diff --git a/Classes/Domain/Model/Renderable/RenderableVariant.php b/Classes/Domain/Model/Renderable/RenderableVariant.php new file mode 100644 index 0000000..b7a7f73 --- /dev/null +++ b/Classes/Domain/Model/Renderable/RenderableVariant.php @@ -0,0 +1,106 @@ +identifier = $identifier; + $this->renderable = $renderable; + + if (isset($options['condition']) && is_string($options['condition'])) { + $this->condition = $options['condition']; + } + + unset($options['condition'], $options['identifier'], $options['variants']); + + $this->options = $options; + } + + /** + * Apply the specified variant to this form element + * regardless of their conditions + */ + public function apply(): void + { + $this->renderable->setOptions($this->options, true); + $this->applied = true; + } + + public function conditionMatches(Resolver $conditionResolver): bool + { + if (empty($this->condition)) { + return false; + } + + return (bool)$conditionResolver->evaluate($this->condition, ['renderable' => $this->renderable]); + } + + public function getIdentifier(): string + { + return $this->identifier; + } + + public function isApplied(): bool + { + return $this->applied; + } +} diff --git a/Classes/Domain/Model/Renderable/RenderableVariantInterface.php b/Classes/Domain/Model/Renderable/RenderableVariantInterface.php new file mode 100644 index 0000000..011a56e --- /dev/null +++ b/Classes/Domain/Model/Renderable/RenderableVariantInterface.php @@ -0,0 +1,40 @@ +formRuntime = $formRuntime; + } + + public function getFormRuntime(): FormRuntime + { + return $this->formRuntime; + } +} diff --git a/Classes/Domain/Renderer/FluidFormRenderer.php b/Classes/Domain/Renderer/FluidFormRenderer.php new file mode 100644 index 0000000..1aab293 --- /dev/null +++ b/Classes/Domain/Renderer/FluidFormRenderer.php @@ -0,0 +1,182 @@ +getType() = Form + * Expected template file: EXT:form/Resources/Private/Frontend/Templates/Form.html + * There is a setting available to set a custom template name. Please read + * the section 'templateName'. + * + * Only the root renderable (FormDefinition) has to be a template file. + * All child renderables are partials. By default, the root renderable + * is called 'Form'. + * + * layoutRootPaths + * --------------- + * + * Used to define several paths for layouts, which will be tried in reversed + * order (the paths are searched from bottom to top). The first folder where + * the desired layout is found, is used. If the array keys are numeric, + * they are first sorted and then tried in reversed order. + * + * partialRootPaths + * ---------------- + * + * Used to define several paths for partials, which will be tried in reversed + * order. The first folder where the desired partial is found, is used. + * The keys of the array define the order. + * + * Within this paths, fluid will search for a file which is named like the + * renderable *type*. + * For example: + * templateRootPaths.10 = EXT:form/Resources/Private/Frontend/Partials/ + * $renderable->getType() = Text + * Expected template file: EXT:form/Resources/Private/Frontend/Partials/Text.html + * There is a setting available to set a custom partial name. Please read + * the section 'templateName'. + * + * templateName + * ----------- + * By default, the renderable type will be taken as the name for the + * template / partial. + * For example: + * partialRootPaths.10 = EXT:form/Resources/Private/Frontend/Partials/ + * $renderable->getType() = Text + * Expected partial file: EXT:form/Resources/Private/Frontend/Partials/Text.html + * + * Set 'templateName' to define a custom name which should be used instead. + * For example: + * templateName = Foo + * $renderable->getType() = Text + * Expected partial file: EXT:form/Resources/Private/Frontend/Partials/Foo.html + * + * Rendering Child Renderables + * =========================== + * + * If a renderable wants to render child renderables, inside its template / partial, + * it can do that using the ViewHelper. + * + * A template example from Page shall demonstrate this: + * + *
+ *   
+ *       
+ *           
+ *               
+ *           
+ *       
+ *   
+ * 
+ * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * @internal + */ +#[Autoconfigure(public: true, shared: false)] +class FluidFormRenderer extends AbstractElementRenderer +{ + public function __construct( + protected readonly ViewFactoryInterface $viewFactory, + private readonly EventDispatcherInterface $eventDispatcher, + ) {} + + /** + * Renders the FormDefinition. + * + * This method is expected to call the 'beforeRendering' hook + * on each renderable. + * This method call the 'beforeRendering' hook initially. + * Each other hooks will be called from the + * renderRenderable viewHelper. + * {@link \TYPO3\CMS\Form\ViewHelpers\RenderRenderableViewHelper::render()} + * + * @return string the rendered $formRuntime + * @internal + */ + public function render(): string + { + $formElementType = $this->formRuntime->getType(); + $renderingOptions = $this->formRuntime->getRenderingOptions(); + if (!isset($renderingOptions['templateRootPaths']) || !is_array($renderingOptions['templateRootPaths'])) { + throw new RenderingException(sprintf('The option templateRootPaths must be set for renderable "%s"', $formElementType), 1480293084); + } + if (!isset($renderingOptions['layoutRootPaths']) || !is_array($renderingOptions['layoutRootPaths'])) { + throw new RenderingException(sprintf('The option layoutRootPaths must be set for renderable "%s"', $formElementType), 1480293085); + } + if (!isset($renderingOptions['partialRootPaths']) || !is_array($renderingOptions['partialRootPaths'])) { + throw new RenderingException(sprintf('The option partialRootPaths must be set for renderable "%s"', $formElementType), 1480293086); + } + $viewFactoryData = new ViewFactoryData( + templateRootPaths: $renderingOptions['templateRootPaths'], + partialRootPaths: $renderingOptions['partialRootPaths'], + layoutRootPaths: $renderingOptions['layoutRootPaths'], + request: $this->getFormRuntime()->getRequest(), + ); + $view = $this->viewFactory->create($viewFactoryData); + $view->assign('form', $this->formRuntime); + if ($view instanceof FluidViewAdapter) { + // @todo: Find a different solution than setting this state here. This happens in other + // ext:form places as well and should vanish to be more non-fluid view friendly. + $view->getRenderingContext() + ->getViewHelperVariableContainer() + ->addOrUpdate(RenderRenderableViewHelper::class, 'formRuntime', $this->formRuntime); + } + $this->eventDispatcher->dispatch(new BeforeRenderableIsRenderedEvent($this->formRuntime->getFormDefinition(), $this->formRuntime)); + return $view->render($this->formRuntime->getTemplateName()); + } +} diff --git a/Classes/Domain/Renderer/RendererInterface.php b/Classes/Domain/Renderer/RendererInterface.php new file mode 100644 index 0000000..a00bc3d --- /dev/null +++ b/Classes/Domain/Renderer/RendererInterface.php @@ -0,0 +1,46 @@ +connectionPool->getQueryBuilderForTable(self::TABLE_NAME); + + $row = $queryBuilder + ->select('*') + ->from(self::TABLE_NAME) + ->where( + $queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid, ParameterType::INTEGER)) + ) + ->executeQuery() + ->fetchAssociative(); + + return $row ?: null; + } + + /** + * Find all form definitions with optional search criteria. + * Returns an array of database rows including full configuration. + */ + public function findAll(SearchCriteria $criteria): array + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME); + + $queryBuilder + ->select('*') + ->from(self::TABLE_NAME); + + $this->applySearchCriteria($queryBuilder, $criteria); + + return $queryBuilder + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * Find all form definitions for listing purposes. + * Returns only metadata columns (uid, pid, identifier, label) without + * the potentially large configuration JSON column. + * + * @return array + */ + public function findAllForListing(SearchCriteria $criteria): array + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME); + + $queryBuilder + ->select('uid', 'pid', 'identifier', 'label') + ->from(self::TABLE_NAME); + + $this->applySearchCriteria($queryBuilder, $criteria); + + return $queryBuilder + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * Check if a form definition with the given form identifier exists. + * Uses a COUNT query on the indexed identifier column for efficiency. + */ + public function existsByFormIdentifier(string $formIdentifier): bool + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME); + + $count = $queryBuilder + ->count('uid') + ->from(self::TABLE_NAME) + ->where( + $queryBuilder->expr()->eq( + 'identifier', + $queryBuilder->createNamedParameter($formIdentifier) + ) + ) + ->executeQuery() + ->fetchOne(); + + return (int)$count > 0; + } + + /** + * Find the UID of a form definition by its form identifier. + * + * Returns the UID of the first matching non-deleted record, or null if not found. + * Used by the upgrade wizard to check for already-migrated forms. + */ + public function findUidByFormIdentifier(string $formIdentifier): ?int + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable(self::TABLE_NAME); + + $uid = $queryBuilder + ->select('uid') + ->from(self::TABLE_NAME) + ->where( + $queryBuilder->expr()->eq( + 'identifier', + $queryBuilder->createNamedParameter($formIdentifier) + ) + ) + ->executeQuery() + ->fetchOne(); + + return $uid !== false ? (int)$uid : null; + } + + /** + * Apply search criteria (search term, limit) to a query builder. + */ + private function applySearchCriteria(QueryBuilder $queryBuilder, SearchCriteria $criteria): void + { + if (!empty($criteria->searchTerm)) { + $queryBuilder->where( + $queryBuilder->expr()->or( + $queryBuilder->expr()->like( + 'identifier', + $queryBuilder->createNamedParameter('%' . $queryBuilder->escapeLikeWildcards($criteria->searchTerm) . '%') + ), + $queryBuilder->expr()->like( + 'label', + $queryBuilder->createNamedParameter('%' . $queryBuilder->escapeLikeWildcards($criteria->searchTerm) . '%') + ) + ) + ); + } + + if ($criteria->hasLimit()) { + $queryBuilder->setMaxResults($criteria->limit); + } + } + + /** + * Insert a form definition in the database. + * @return int|null UID of the newly created record or null on failure. + * @throws \JsonException + */ + public function add(string $persistenceIdentifier, int $pid, FormData $formDefinition): ?int + { + $formDefinitionJson = json_encode($this->jsonObjectKeyOrderPreserver->protect($formDefinition->toArray()), JSON_THROW_ON_ERROR); + $fields = [ + 'pid' => $pid, + 'label' => $formDefinition->name, + 'identifier' => $formDefinition->identifier, + 'configuration' => $formDefinitionJson, + ]; + + $this->persistenceGuard->allowInvocation(FormDefinitionPersistenceCommand::Create, $persistenceIdentifier, $fields); + /** @var DataHandler $dataHandler */ + $dataHandler = GeneralUtility::makeInstance(DataHandler::class); + $dataHandler->start([self::TABLE_NAME => [$persistenceIdentifier => $fields]], []); + try { + $dataHandler->process_datamap(); + } finally { + $this->persistenceGuard->consumeInvocation(FormDefinitionPersistenceCommand::Create, $persistenceIdentifier, $fields); + } + + if ($dataHandler->errorLog !== []) { + return null; + } + + return isset($dataHandler->substNEWwithIDs[$persistenceIdentifier]) + ? (int)$dataHandler->substNEWwithIDs[$persistenceIdentifier] + : null; + } + + /** + * Insert a form definition using a raw database insert (no DataHandler). + * + * This method is intended for contexts where DataHandler cannot be used, + * e.g. the Install Tool upgrade wizard where no backend user is available. + * + * @return int|null The UID of the newly created record, or null on failure + */ + public function addRaw(int $pid, FormData $formDefinition): ?int + { + $connection = $this->connectionPool->getConnectionForTable(self::TABLE_NAME); + $connection->insert(self::TABLE_NAME, [ + 'pid' => $pid, + 'deleted' => 0, + 'label' => $formDefinition->name, + 'identifier' => $formDefinition->identifier, + 'configuration' => $this->jsonObjectKeyOrderPreserver->protect($formDefinition->toArray()), + 'crdate' => $GLOBALS['EXEC_TIME'] ?? time(), + 'tstamp' => $GLOBALS['EXEC_TIME'] ?? time(), + ]); + $uid = (int)$connection->lastInsertId(); + return $uid > 0 ? $uid : null; + } + + /** + * Removes a form definition completely from the system using DataHandler. + * + * @param int $uid The UID representing the form definition to delete + * @return bool TRUE if the form definition was successfully deleted, FALSE otherwise + */ + public function remove(int $uid): bool + { + $this->persistenceGuard->allowInvocation(FormDefinitionPersistenceCommand::Delete, $uid); + /** @var DataHandler $dataHandler */ + $dataHandler = GeneralUtility::makeInstance(DataHandler::class); + $dataHandler->start([], [self::TABLE_NAME => [$uid => ['delete' => 1]]]); + try { + $dataHandler->process_cmdmap(); + } finally { + $this->persistenceGuard->consumeInvocation(FormDefinitionPersistenceCommand::Delete, $uid); + } + return $dataHandler->errorLog === []; + } + + /** + * Update a form definition in the database using DataHandler. + * + * @param int $uid The UID of the form definition to update + * @param FormData $formDefinition + * @return bool TRUE if update was successful, FALSE otherwise + * @throws \JsonException + */ + public function update(int $uid, FormData $formDefinition): bool + { + if (empty($uid)) { + return false; + } + + $formDefinitionJson = json_encode($this->jsonObjectKeyOrderPreserver->protect($formDefinition->toArray()), JSON_THROW_ON_ERROR); + $fields = [ + 'label' => $formDefinition->name, + 'identifier' => $formDefinition->identifier, + 'configuration' => $formDefinitionJson, + ]; + + $this->persistenceGuard->allowInvocation(FormDefinitionPersistenceCommand::Update, $uid, $fields); + /** @var DataHandler $dataHandler */ + $dataHandler = GeneralUtility::makeInstance(DataHandler::class); + $dataHandler->start([self::TABLE_NAME => [$uid => $fields]], []); + try { + $dataHandler->process_datamap(); + } finally { + $this->persistenceGuard->consumeInvocation(FormDefinitionPersistenceCommand::Update, $uid, $fields); + } + + return $dataHandler->errorLog === []; + } +} diff --git a/Classes/Domain/Runtime/Exception/PropertyMappingException.php b/Classes/Domain/Runtime/Exception/PropertyMappingException.php new file mode 100644 index 0000000..e1c31ec --- /dev/null +++ b/Classes/Domain/Runtime/Exception/PropertyMappingException.php @@ -0,0 +1,27 @@ +bind($request); + * $renderedForm = $form->render(); + * \--- + * + * Accessing Form Values + * ===================== + * + * In order to get the values the user has entered into the form, you can access + * this object like an array: If a form field with the identifier *firstName* + * exists, you can do **$form['firstName']** to retrieve its current value. + * + * You can also set values in the same way. + * + * Rendering Internals + * =================== + * + * The FormRuntime asks the FormDefinition about the configured Renderer + * which should be used ({@link \TYPO3\CMS\Form\Domain\Model\FormDefinition::getRendererClassName}), + * and then trigger render() on this Renderer. + * + * This makes it possible to declaratively define how a form should be rendered. + * + * Scope: frontend + * **This class is NOT meant to be sub classed by developers.** + * + * @internal High cohesion to FormDefinition, may change any time + * @todo: Declare final in v12 + */ +#[Autoconfigure(public: true, shared: false)] +class FormRuntime implements RootRenderableInterface, \ArrayAccess +{ + public const HONEYPOT_NAME_SESSION_IDENTIFIER = 'tx_form_honeypot_name_'; + + protected FormDefinition $formDefinition; + protected RequestInterface $request; + protected ResponseInterface $response; + + /** + * @var FormState + */ + protected $formState; + + /** + * Individual unique random form session identifier valid + * for current user session. This value is not persisted server-side. + * + * @var FormSession|null + */ + protected $formSession; + + /** + * The current page is the page which will be displayed to the user + * during rendering. + * + * If $currentPage is NULL, the *last* page has been submitted and + * finishing actions need to take place. You should use $this->isAfterLastPage() + * instead of explicitly checking for NULL. + * + * @var Page|null + */ + protected $currentPage; + + /** + * Reference to the page which has been shown on the last request (i.e. + * we have to handle the submitted data from lastDisplayedPage) + * + * @var Page + */ + protected $lastDisplayedPage; + + /** + * The current site language configuration. + * + * @var SiteLanguage + */ + protected $currentSiteLanguage; + + /** + * Reference to the current running finisher + * + * @var FinisherInterface + */ + protected $currentFinisher; + + public function __construct( + protected readonly ContainerInterface $container, + protected readonly ConfigurationManagerInterface $configurationManager, + protected readonly HashService $hashService, + protected readonly ValidatorResolver $validatorResolver, + private readonly Context $context, + private readonly EventDispatcherInterface $eventDispatcher, + ) { + $this->response = new Response(); + } + + public function setFormDefinition(FormDefinition $formDefinition) + { + $this->formDefinition = $formDefinition; + } + + public function setRequest(RequestInterface $request) + { + $this->request = clone $request; + } + + public function initialize() + { + $arguments = $this->request->getArguments(); + $formIdentifier = $this->formDefinition->getIdentifier(); + if (isset($arguments[$formIdentifier])) { + $this->request = $this->request->withArguments($arguments[$formIdentifier]); + } + + $this->initializeCurrentSiteLanguage(); + $this->initializeFormSessionFromRequest(); + $this->initializeFormStateFromRequest(); + $this->triggerAfterFormStateInitialized(); + $this->processVariants(); + $this->initializeCurrentPageFromRequest(); + $this->initializeHoneypotFromRequest(); + + // Only validate and set form values within the form state + // if the current request is not the very first request + // and the current request can be processed (POST request and uncached). + if (!$this->isFirstRequest() && $this->canProcessFormSubmission()) { + $this->processSubmittedFormValues(); + } + + $this->renderHoneypot(); + } + + /** + * @todo `FormRuntime::$formSession` is still vulnerable to session fixation unless a real cookie-based process is used + */ + protected function initializeFormSessionFromRequest(): void + { + // Initialize the form session only if the current request can be processed + // (POST request and uncached) to ensure unique sessions for each form submitter. + if (!$this->canProcessFormSubmission()) { + return; + } + + /** @var ExtbaseRequestParameters $extbaseRequestParameters */ + $extbaseRequestParameters = $this->request->getAttribute('extbase'); + $sessionIdentifierFromRequest = $extbaseRequestParameters->getInternalArgument('__session'); + $this->formSession = GeneralUtility::makeInstance(FormSession::class, $sessionIdentifierFromRequest); + } + + /** + * Initializes the current state of the form, based on the request + * @throws BadRequestException + */ + protected function initializeFormStateFromRequest() + { + // Only try to reconstitute the form state if the current request + // is not the very first request and if the current request can + // be processed (POST request and uncached). + /** @var ExtbaseRequestParameters $extbaseRequestParameters */ + $extbaseRequestParameters = $this->request->getAttribute('extbase'); + $serializedFormStateWithHmac = $extbaseRequestParameters->getInternalArgument('__state'); + if ($serializedFormStateWithHmac === null || !$this->canProcessFormSubmission()) { + $this->formState = GeneralUtility::makeInstance(FormState::class); + } else { + try { + $serializedFormState = $this->hashService->validateAndStripHmac($serializedFormStateWithHmac, HashScope::FormState->prefix(), HashAlgo::SHA3_256); + } catch (InvalidHashStringException $e) { + throw new BadRequestException('The HMAC of the form state could not be validated.', 1581862823); + } + /* @phpstan-ignore unserialize.allowedClasses.insecure (Integrity check already happens via HMAC validation) */ + $this->formState = unserialize(base64_decode($serializedFormState), ['allowed_classes' => true]); + } + } + + protected function triggerAfterFormStateInitialized(): void + { + $this->eventDispatcher->dispatch( + new AfterFormStateInitializedEvent($this, $this->request) + ); + } + + /** + * Initializes the current page data based on the current request, also modifiable by a hook + */ + protected function initializeCurrentPageFromRequest(): void + { + // If there was no previous form submissions or if the current request + // can't be processed (no POST request and/or cached) then display the first + // form step + if (!$this->formState->isFormSubmitted() || !$this->canProcessFormSubmission()) { + $this->currentPage = $this->formDefinition->getPageByIndex(0); + + if (!$this->currentPage->isEnabled()) { + throw new FormException('Disabling the first page is not allowed', 1527186844); + } + $this->dispatchCurrentPageInitializedEvent(); + return; + } + + $this->lastDisplayedPage = $this->formDefinition->getPageByIndex($this->formState->getLastDisplayedPageIndex()); + $currentPageIndex = $this->determineCurrentPageIndex(); + + if ($this->isLastPage($currentPageIndex)) { + $this->currentPage = null; + } else { + $this->currentPage = $this->formDefinition->getPageByIndex($currentPageIndex); + if (!$this->currentPage->isEnabled()) { + if ($currentPageIndex === 0) { + throw new FormException('Disabling the first page is not allowed', 1527186845); + } + if ($this->userWentBackToPreviousStep()) { + $this->currentPage = $this->getPreviousEnabledPage(); + } else { + $this->currentPage = $this->getNextEnabledPage(); + } + } + } + $this->dispatchCurrentPageInitializedEvent($this->lastDisplayedPage); + } + + private function isLastPage(int $currentPageIndex): bool + { + return $currentPageIndex >= count($this->formDefinition->getPages()); + } + + /** + * Get the current page index by resolving the request + */ + private function determineCurrentPageIndex(): int + { + /** @var ExtbaseRequestParameters $extbaseRequestParameters */ + $extbaseRequestParameters = $this->request->getAttribute('extbase'); + $currentPageIndex = (int)$extbaseRequestParameters->getInternalArgument('__currentPage'); + if ($this->userWentBackToPreviousStep()) { + if ($currentPageIndex < $this->lastDisplayedPage->getIndex()) { + $currentPageIndex = $this->lastDisplayedPage->getIndex(); + } + } else { + if ($currentPageIndex > $this->lastDisplayedPage->getIndex() + 1) { + $currentPageIndex = $this->lastDisplayedPage->getIndex() + 1; + } + } + return $currentPageIndex; + } + + /** + * Dispatches the AfterCurrentPageIsInitializedEvent event and sets the current page + */ + private function dispatchCurrentPageInitializedEvent(?Page $lastDisplayedPage = null): void + { + $event = $this->eventDispatcher->dispatch( + new AfterCurrentPageIsResolvedEvent( + $this->currentPage, + $this, + $lastDisplayedPage, + $this->request, + ) + ); + $this->currentPage = $event->currentPage; + } + + /** + * Checks if the honey pot is active, and adds a validator if so. + */ + protected function initializeHoneypotFromRequest() + { + $renderingOptions = $this->formDefinition->getRenderingOptions(); + if (!isset($renderingOptions['honeypot']['enable']) + || $renderingOptions['honeypot']['enable'] === false + || ApplicationType::fromRequest($this->request)->isBackend() + ) { + return; + } + + ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']); + + if (!$this->isFirstRequest()) { + $elementsCount = count($this->lastDisplayedPage->getElements()); + if ($elementsCount === 0) { + return; + } + + $honeypotNameFromSession = $this->getHoneypotNameFromSession($this->lastDisplayedPage); + if ($honeypotNameFromSession) { + $honeypotElement = $this->lastDisplayedPage->createElement($honeypotNameFromSession, $renderingOptions['honeypot']['formElementToUse']); + $validator = $this->validatorResolver->createValidator(EmptyValidator::class, [], $this->request); + $honeypotElement->addValidator($validator); + } + } + } + + /** + * Renders a hidden field if the honey pot is active. + */ + protected function renderHoneypot() + { + $renderingOptions = $this->formDefinition->getRenderingOptions(); + if (!isset($renderingOptions['honeypot']['enable']) + || $this->currentPage === null + || $renderingOptions['honeypot']['enable'] === false + || ApplicationType::fromRequest($this->request)->isBackend() + ) { + return; + } + + ArrayUtility::assertAllArrayKeysAreValid($renderingOptions['honeypot'], ['enable', 'formElementToUse']); + + if (!$this->isAfterLastPage()) { + $elementsCount = count($this->currentPage->getElements()); + if ($elementsCount === 0) { + return; + } + + if (!$this->isFirstRequest()) { + $honeypotNameFromSession = $this->getHoneypotNameFromSession($this->lastDisplayedPage); + if ($honeypotNameFromSession) { + $honeypotElement = $this->formDefinition->getElementByIdentifier($honeypotNameFromSession); + if ($honeypotElement instanceof FormElementInterface) { + $this->lastDisplayedPage->removeElement($honeypotElement); + } + } + } + + $elementsCount = count($this->currentPage->getElements()); + $randomElementNumber = random_int(0, $elementsCount - 1); + $honeypotName = substr(str_shuffle('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'), 0, random_int(5, 26)); + + $referenceElement = $this->currentPage->getElements()[$randomElementNumber]; + $honeypotElement = $this->currentPage->createElement($honeypotName, $renderingOptions['honeypot']['formElementToUse']); + $validator = $this->validatorResolver->createValidator(EmptyValidator::class, [], $this->request); + + $honeypotElement->addValidator($validator); + if (random_int(0, 1) === 1) { + $this->currentPage->moveElementAfter($honeypotElement, $referenceElement); + } else { + $this->currentPage->moveElementBefore($honeypotElement, $referenceElement); + } + $this->setHoneypotNameInSession($this->currentPage, $honeypotName); + } + } + + /** + * @return string|null + */ + protected function getHoneypotNameFromSession(Page $page) + { + if ($this->isFrontendUserAuthenticated()) { + $honeypotNameFromSession = $this->getFrontendUser()->getKey( + 'user', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier() + ); + } else { + $honeypotNameFromSession = $this->getFrontendUser()->getKey( + 'ses', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier() + ); + } + return $honeypotNameFromSession; + } + + protected function setHoneypotNameInSession(Page $page, string $honeypotName) + { + if ($this->isFrontendUserAuthenticated()) { + $this->getFrontendUser()->setKey( + 'user', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier(), + $honeypotName + ); + } else { + $this->getFrontendUser()->setKey( + 'ses', + self::HONEYPOT_NAME_SESSION_IDENTIFIER . $this->getIdentifier() . $page->getIdentifier(), + $honeypotName + ); + } + } + + /** + * Necessary to know if honeypot information should be stored in the user session info, or in the anonymous session. + */ + protected function isFrontendUserAuthenticated(): bool + { + return (bool)$this->context->getPropertyFromAspect('frontend.user', 'isLoggedIn', false); + } + + protected function processVariants(): void + { + $conditionResolver = $this->getConditionResolver(); + $renderables = array_merge([$this->formDefinition], $this->formDefinition->getRenderablesRecursively()); + foreach ($renderables as $renderable) { + if ($renderable instanceof VariableRenderableInterface) { + $variants = $renderable->getVariants(); + foreach ($variants as $variant) { + if ($variant->conditionMatches($conditionResolver)) { + $variant->apply(); + } + } + } + } + } + + /** + * Returns TRUE if the last page of the form has been submitted, otherwise FALSE + */ + protected function isAfterLastPage(): bool + { + return $this->currentPage === null; + } + + /** + * Returns TRUE if no previous page is stored in the FormState, otherwise FALSE + */ + protected function isFirstRequest(): bool + { + return $this->lastDisplayedPage === null; + } + + protected function isPostRequest(): bool + { + return $this->getRequest()->getMethod() === 'POST'; + } + + /** + * Determine whether the surrounding content object is cached. + * If no surrounding content object can be found (which would be strange) + * we assume a cached request for safety which means that an empty form + * will be rendered. + */ + protected function isRenderedCached(): bool + { + $contentObject = $this->request->getAttribute('currentContentObject'); + // @todo: this does not work when rendering a cached `FLUIDTEMPLATE` (not nested in `COA_INT`) + // Rendering the form other than with the controller, will never work out cleanly. + // This likely can only be resolved by deprecating using the form render view helper + // other than in a template for the form plugin and covering the use cases the VH was introduced + // with a different concept + return $contentObject === null || $contentObject->getUserObjectType() === ContentObjectRenderer::OBJECTTYPE_USER; + } + + /** + * Runs through all validations + */ + protected function processSubmittedFormValues() + { + $result = $this->mapAndValidatePage($this->lastDisplayedPage); + if ($result->hasErrors() && !$this->userWentBackToPreviousStep()) { + $this->currentPage = $this->lastDisplayedPage; + /** @var ExtbaseRequestParameters $extbaseRequestParameters */ + $extbaseRequestParameters = clone $this->request->getAttribute('extbase'); + $extbaseRequestParameters->setOriginalRequestMappingResults($result); + $this->request = $this->request->withAttribute('extbase', $extbaseRequestParameters); + } + } + + /** + * returns TRUE if the user went back to any previous step in the form. + */ + protected function userWentBackToPreviousStep(): bool + { + return !$this->isAfterLastPage() && !$this->isFirstRequest() && $this->currentPage->getIndex() < $this->lastDisplayedPage->getIndex(); + } + + /** + * @throws PropertyMappingException + */ + protected function mapAndValidatePage(Page $page): Result + { + $result = GeneralUtility::makeInstance(Result::class); + $requestArguments = $this->request->getArguments(); + + $propertyPathsForWhichPropertyMappingShouldHappen = []; + $registerPropertyPaths = static function ($propertyPath) use (&$propertyPathsForWhichPropertyMappingShouldHappen) { + $propertyPathParts = explode('.', $propertyPath); + $accumulatedPropertyPathParts = []; + foreach ($propertyPathParts as $propertyPathPart) { + $accumulatedPropertyPathParts[] = $propertyPathPart; + $temporaryPropertyPath = implode('.', $accumulatedPropertyPathParts); + $propertyPathsForWhichPropertyMappingShouldHappen[$temporaryPropertyPath] = $temporaryPropertyPath; + } + }; + + $this->eventDispatcher->dispatch( + new BeforeRenderableIsValidatedEvent( + null, + $this, + $page, + $this->request, + ) + ); + + foreach ($page->getElementsRecursively() as $element) { + if (!$this->isRenderableEnabled($element)) { + continue; + } + + try { + $value = ArrayUtility::getValueByPath($requestArguments, $element->getIdentifier(), '.'); + } catch (MissingArrayPathException $exception) { + $value = null; + } + + $event = $this->eventDispatcher->dispatch( + new BeforeRenderableIsValidatedEvent( + $value, + $this, + $element, + $this->request, + ) + ); + $value = $event->value; + + $this->formState->setFormValue($element->getIdentifier(), $value); + $registerPropertyPaths($element->getIdentifier()); + } + + // The more parts the path has, the more early it is processed + usort($propertyPathsForWhichPropertyMappingShouldHappen, static function ($a, $b) { + return substr_count($b, '.') - substr_count($a, '.'); + }); + + $processingRules = $this->formDefinition->getProcessingRules(); + + foreach ($propertyPathsForWhichPropertyMappingShouldHappen as $propertyPath) { + if (isset($processingRules[$propertyPath])) { + $processingRule = $processingRules[$propertyPath]; + $value = $this->formState->getFormValue($propertyPath); + try { + $value = $processingRule->process($value); + } catch (PropertyException $exception) { + throw new PropertyMappingException( + 'Failed to process FormValue at "' . $propertyPath . '" from "' . gettype($value) . '" to "' . $processingRule->getDataType() . '"', + 1480024933, + $exception + ); + } + $result->forProperty($this->getIdentifier() . '.' . $propertyPath)->merge($processingRule->getProcessingMessages()); + $this->formState->setFormValue($propertyPath, $value); + } + } + + return $result; + } + + /** + * Override the current page taken from the request, rendering the page with index $pageIndex instead. + * + * This is typically not needed in production code, but it is very helpful when displaying + * some kind of "preview" of the form (e.g. form editor). + * + * @param int $pageIndex + */ + public function overrideCurrentPage(int $pageIndex) + { + $this->currentPage = $this->formDefinition->getPageByIndex($pageIndex); + } + + /** + * Render this form. + * + * @return string|null rendered form + * @throws RenderingException + */ + public function render() + { + if ($this->isAfterLastPage()) { + return $this->invokeFinishers(); + } + $this->processVariants(); + + $this->formState->setLastDisplayedPageIndex($this->currentPage->getIndex()); + + if ($this->formDefinition->getRendererClassName() === '') { + throw new RenderingException(sprintf('The form definition "%s" does not have a rendererClassName set.', $this->formDefinition->getIdentifier()), 1326095912); + } + $rendererClassName = $this->formDefinition->getRendererClassName(); + $renderer = $this->container->get($rendererClassName); + if (!($renderer instanceof RendererInterface)) { + throw new RenderingException(sprintf('The renderer "%s" des not implement RendererInterface', $rendererClassName), 1326096024); + } + + $renderer->setFormRuntime($this); + return $renderer->render(); + } + + /** + * Executes all finishers of this form + */ + protected function invokeFinishers(): string + { + $finisherContext = GeneralUtility::makeInstance( + FinisherContext::class, + $this, + $this->request + ); + + $output = ''; + $this->response->getBody()->rewind(); + $originalContent = $this->response->getBody()->getContents(); + $this->response->getBody()->write(''); + foreach ($this->formDefinition->getFinishers() as $finisher) { + $this->currentFinisher = $finisher; + $this->processVariants(); + + $finisherOutput = $finisher->execute($finisherContext); + if (is_string($finisherOutput) && !empty($finisherOutput)) { + $output .= $finisherOutput; + } else { + $this->response->getBody()->rewind(); + $output .= $this->response->getBody()->getContents(); + $this->response->getBody()->write(''); + } + + if ($finisherContext->isCancelled()) { + break; + } + } + $this->response->getBody()->rewind(); + $this->response->getBody()->write($originalContent); + + return $output; + } + + /** + * @return string The identifier of underlying form + */ + public function getIdentifier(): string + { + return $this->formDefinition->getIdentifier(); + } + + /** + * Get the request this object is bound to. + * + * This is mostly relevant inside Finishers, where you f.e. want to redirect + * the user to another page. + * + * @return RequestInterface The request this object is bound to + */ + public function getRequest(): RequestInterface + { + return $this->request; + } + + /** + * Get the response this object is bound to. + * + * This is mostly relevant inside Finishers, where you f.e. want to set response + * headers or output content. + * + * @return ResponseInterface the response this object is bound to + */ + public function getResponse(): ResponseInterface + { + return $this->response; + } + + /** + * Only process values if there is a post request and if the + * surrounding content object is uncached. + * Is this not the case, all possible submitted values will be discarded + * and the first form step will be shown with an empty form state. + * + * @internal + */ + public function canProcessFormSubmission(): bool + { + return $this->isPostRequest() && !$this->isRenderedCached(); + } + + /** + * @internal + */ + public function getFormSession(): ?FormSession + { + return $this->formSession; + } + + /** + * Returns the currently selected page + */ + public function getCurrentPage(): ?Page + { + return $this->currentPage; + } + + /** + * Returns the previous page of the currently selected one or NULL if there is no previous page + */ + public function getPreviousPage(): ?Page + { + $previousPageIndex = $this->currentPage->getIndex() - 1; + if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) { + return $this->formDefinition->getPageByIndex($previousPageIndex); + } + return null; + } + + /** + * Returns the next page of the currently selected one or NULL if there is no next page + */ + public function getNextPage(): ?Page + { + $nextPageIndex = $this->currentPage->getIndex() + 1; + if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) { + return $this->formDefinition->getPageByIndex($nextPageIndex); + } + return null; + } + + /** + * Returns the previous enabled page of the currently selected one + * or NULL if there is no previous page + */ + public function getPreviousEnabledPage(): ?Page + { + $previousPage = null; + $previousPageIndex = $this->currentPage->getIndex() - 1; + while ($previousPageIndex >= 0) { + if ($this->formDefinition->hasPageWithIndex($previousPageIndex)) { + $previousPage = $this->formDefinition->getPageByIndex($previousPageIndex); + + if ($previousPage->isEnabled()) { + break; + } + + $previousPage = null; + $previousPageIndex--; + } else { + $previousPage = null; + break; + } + } + + return $previousPage; + } + + /** + * Returns the next enabled page of the currently selected one or + * NULL if there is no next page + */ + public function getNextEnabledPage(): ?Page + { + $nextPage = null; + $pageCount = count($this->formDefinition->getPages()); + $nextPageIndex = $this->currentPage->getIndex() + 1; + + while ($nextPageIndex < $pageCount) { + if ($this->formDefinition->hasPageWithIndex($nextPageIndex)) { + $nextPage = $this->formDefinition->getPageByIndex($nextPageIndex); + $renderingOptions = $nextPage->getRenderingOptions(); + if ( + !isset($renderingOptions['enabled']) + || (bool)$renderingOptions['enabled'] + ) { + break; + } + $nextPage = null; + $nextPageIndex++; + } else { + $nextPage = null; + break; + } + } + + return $nextPage; + } + + /** + * Abstract "type" of this Renderable. Is used during the rendering process + * to determine the template file or the View PHP class being used to render + * the particular element. + */ + public function getType(): string + { + return $this->formDefinition->getType(); + } + + /** + * @param string $identifier + * @internal + */ + public function offsetExists(mixed $identifier): bool + { + $identifier = (string)$identifier; + if ($this->getElementValue($identifier) !== null) { + return true; + } + + if (is_callable([$this, 'get' . ucfirst($identifier)])) { + return true; + } + if (is_callable([$this, 'has' . ucfirst($identifier)])) { + return true; + } + if (is_callable([$this, 'is' . ucfirst($identifier)])) { + return true; + } + if (property_exists($this, $identifier)) { + $propertyReflection = new \ReflectionProperty($this, $identifier); + return $propertyReflection->isPublic(); + } + + return false; + } + + /** + * @param string $identifier + * @internal + */ + public function offsetGet(mixed $identifier): mixed + { + $identifier = (string)$identifier; + if ($this->getElementValue($identifier) !== null) { + return $this->getElementValue($identifier); + } + $getterMethodName = 'get' . ucfirst($identifier); + if (is_callable([$this, $getterMethodName])) { + return $this->{$getterMethodName}(); + } + return null; + } + + /** + * @param string $identifier + * @internal + */ + public function offsetSet(mixed $identifier, mixed $value): void + { + $identifier = (string)$identifier; + $this->formState->setFormValue($identifier, $value); + } + + /** + * @param string $identifier + * @internal + */ + public function offsetUnset(mixed $identifier): void + { + $identifier = (string)$identifier; + $this->formState->setFormValue($identifier, null); + } + + /** + * Returns the value of the specified element + * + * @return mixed + */ + public function getElementValue(string $identifier) + { + $formValue = $this->formState->getFormValue($identifier); + if ($formValue !== null) { + return $formValue; + } + return $this->formDefinition->getElementDefaultValueByIdentifier($identifier); + } + + /** + * @return array|Page[] The Form's pages in the correct order + */ + public function getPages(): array + { + return $this->formDefinition->getPages(); + } + + /** + * @internal + */ + public function getFormState(): ?FormState + { + return $this->formState; + } + + /** + * Get all rendering options + * + * @return array associative array of rendering options + */ + public function getRenderingOptions(): array + { + return $this->formDefinition->getRenderingOptions(); + } + + /** + * Get the renderer class name to be used to display this renderable; + * must implement RendererInterface + * + * @return string the renderer class name + */ + public function getRendererClassName(): string + { + return $this->formDefinition->getRendererClassName(); + } + + /** + * Get the label which shall be displayed next to the form element + */ + public function getLabel(): string + { + return $this->formDefinition->getLabel(); + } + + /** + * Get the template name of the renderable + */ + public function getTemplateName(): string + { + return $this->formDefinition->getTemplateName(); + } + + /** + * Get the underlying form definition from the runtime + */ + public function getFormDefinition(): FormDefinition + { + return $this->formDefinition; + } + + /** + * Get the current site language configuration. + * + * @return SiteLanguage + */ + public function getCurrentSiteLanguage(): ?SiteLanguage + { + return $this->currentSiteLanguage; + } + + /** + * Override the current site language configuration. + * + * This is typically not needed in production code, but it is very + * helpful when displaying some kind of "preview" of the form (e.g. form editor). + * + * @param SiteLanguage $currentSiteLanguage + */ + public function setCurrentSiteLanguage(SiteLanguage $currentSiteLanguage): void + { + $this->currentSiteLanguage = $currentSiteLanguage; + } + + /** + * Initialize the SiteLanguage object. + * This is mainly used by the condition matcher. + */ + protected function initializeCurrentSiteLanguage(): void + { + if ($this->request->getAttribute('language') instanceof SiteLanguage) { + $this->currentSiteLanguage = $this->request->getAttribute('language'); + } else { + $languageId = (int)$this->context->getPropertyFromAspect('language', 'id', 0); + $pageId = $this->request->getAttribute('frontend.page.information')?->getId() ?? 0; + $fakeSiteConfiguration = [ + 'languages' => [ + [ + 'languageId' => $languageId, + 'title' => 'Dummy', + 'navigationTitle' => '', + 'flag' => '', + 'locale' => '', + ], + ], + ]; + $this->currentSiteLanguage = GeneralUtility::makeInstance(Site::class, 'form-dummy', $pageId, $fakeSiteConfiguration) + ->getLanguageById($languageId); + } + } + + /** + * Reference to the current running finisher + */ + public function getCurrentFinisher(): ?FinisherInterface + { + return $this->currentFinisher; + } + + protected function getConditionResolver(): Resolver + { + $formValues = array_replace_recursive( + $this->getFormState()->getFormValues(), + $this->getRequest()->getArguments() + ); + $page = $this->getCurrentPage(); + $stepIdentifier = $page !== null ? $page->getIdentifier() : ''; + $stepType = $page !== null ? $page->getType() : ''; + + $finisherIdentifier = ''; + if ($this->getCurrentFinisher() !== null) { + if (method_exists($this->getCurrentFinisher(), 'getFinisherIdentifier')) { + $finisherIdentifier = $this->getCurrentFinisher()->getFinisherIdentifier(); + } else { + $finisherIdentifier = (new \ReflectionClass($this->getCurrentFinisher()))->getShortName(); + $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier); + } + } + + $contentObjectData = $this->request->getAttribute('currentContentObject')->data ?? []; + + return GeneralUtility::makeInstance( + Resolver::class, + 'form', + [ + 'formRuntime' => $this, + 'formValues' => $formValues, + 'stepIdentifier' => $stepIdentifier, + 'stepType' => $stepType, + 'finisherIdentifier' => $finisherIdentifier, + 'contentObject' => $contentObjectData, + 'request' => new RequestWrapper($this->getRequest()), + 'site' => $this->getRequest()->getAttribute('site'), + 'siteLanguage' => $this->getRequest()->getAttribute('language'), + ] + ); + } + + protected function getFrontendUser(): FrontendUserAuthentication + { + return $this->request->getAttribute('frontend.user'); + } + + protected function isRenderableEnabled(RenderableInterface $renderable): bool + { + if (!$renderable->isEnabled()) { + return false; + } + + while ($renderable = $renderable->getParentRenderable()) { + if ($renderable instanceof RenderableInterface && !$renderable->isEnabled()) { + return false; + } + } + + return true; + } +} diff --git a/Classes/Domain/Runtime/FormRuntime/FormSession.php b/Classes/Domain/Runtime/FormRuntime/FormSession.php new file mode 100644 index 0000000..c2a930d --- /dev/null +++ b/Classes/Domain/Runtime/FormRuntime/FormSession.php @@ -0,0 +1,88 @@ +identifier = $this->generateIdentifier(); + } else { + $this->identifier = $this->validateIdentifier($authenticatedIdentifier); + } + } + + /** + * @internal + */ + public function getIdentifier(): string + { + return $this->identifier; + } + + /** + * Consumed by TYPO3\CMS\Form\ViewHelpers\FormViewHelper + * + * @internal + */ + public function getAuthenticatedIdentifier(): string + { + return GeneralUtility::makeInstance(HashService::class) + // restrict string expansion by adding some char ('|') + ->appendHmac($this->identifier . '|', HashScope::FormSession->prefix(), HashAlgo::SHA3_256); + } + + protected function generateIdentifier(): string + { + return GeneralUtility::makeInstance(Random::class)->generateRandomHexString(40); + } + + /** + * @throws BadRequestException + */ + protected function validateIdentifier(string $authenticatedIdentifier): string + { + try { + $identifier = GeneralUtility::makeInstance(HashService::class) + ->validateAndStripHmac($authenticatedIdentifier, HashScope::FormSession->prefix(), HashAlgo::SHA3_256); + return rtrim($identifier, '|'); + } catch (InvalidHashStringException $e) { + throw new BadRequestException('The HMAC of the form session could not be validated.', 1613300274); + } + } +} diff --git a/Classes/Domain/Runtime/FormState.php b/Classes/Domain/Runtime/FormState.php new file mode 100644 index 0000000..6c9a123 --- /dev/null +++ b/Classes/Domain/Runtime/FormState.php @@ -0,0 +1,102 @@ +lastDisplayedPageIndex !== self::NOPAGE; + } + + public function getLastDisplayedPageIndex(): int + { + return $this->lastDisplayedPageIndex; + } + + public function setLastDisplayedPageIndex(int $lastDisplayedPageIndex) + { + $this->lastDisplayedPageIndex = $lastDisplayedPageIndex; + } + + public function getFormValues(): array + { + return $this->formValues; + } + + /** + * @param mixed $value + */ + public function setFormValue(string $propertyPath, $value) + { + $this->formValues = ArrayUtility::setValueByPath( + $this->formValues, + $propertyPath, + $value, + '.' + ); + } + + /** + * @return mixed + */ + public function getFormValue(string $propertyPath) + { + try { + return ArrayUtility::getValueByPath($this->formValues, $propertyPath, '.'); + } catch (MissingArrayPathException $exception) { + return null; + } + } +} diff --git a/Classes/Domain/Translation/FormTranslationKeychainBuilder.php b/Classes/Domain/Translation/FormTranslationKeychainBuilder.php new file mode 100644 index 0000000..0fb9116 --- /dev/null +++ b/Classes/Domain/Translation/FormTranslationKeychainBuilder.php @@ -0,0 +1,272 @@ + + */ + public function buildForElementProperty( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.element.%s.%s.%s', $translationFile, $originalFormIdentifier, $elementIdentifier, $propertyType, $property); + } + array_push($chain, ...$this->buildElementPropertyKeys($translationFile, $formIdentifier, $elementIdentifier, $elementType, $propertyType, $property)); + } + return $chain; + } + + /** + * Builds the keychain for a scalar property on the FormRuntime itself, + * where the original form identifier is used as the element segment. + * + * @param string[] $translationFiles + * @return list + */ + public function buildForFormRuntimeProperty( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.element.%s.%s.%s', $translationFile, $originalFormIdentifier, $originalFormIdentifier, $propertyType, $property); + $chain[] = sprintf('%s:element.%s.%s.%s', $translationFile, $originalFormIdentifier, $propertyType, $property); + } + array_push($chain, ...$this->buildElementPropertyKeys($translationFile, $formIdentifier, $elementIdentifier, $elementType, $propertyType, $property)); + } + return $chain; + } + + /** + * Builds the keychain for a single option entry inside an "options" + * array property on a regular element (e.g. Select / RadioButton / Checkbox groups). + * + * @param string[] $translationFiles + * @return list + */ + public function buildForElementOption( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property, + string|int $optionValue, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.element.%s.%s.%s.%s', $translationFile, $originalFormIdentifier, $elementIdentifier, $propertyType, $property, $optionValue); + } + array_push($chain, ...$this->buildElementOptionKeys($translationFile, $formIdentifier, $elementIdentifier, $elementType, $propertyType, $property, $optionValue)); + } + return $chain; + } + + /** + * Builds the keychain for a single option entry on the FormRuntime itself, + * where the original form identifier is used as the element segment. + * + * @param string[] $translationFiles + * @return list + */ + public function buildForFormRuntimeOption( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property, + string|int $optionValue, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.element.%s.%s.%s.%s', $translationFile, $originalFormIdentifier, $originalFormIdentifier, $propertyType, $property, $optionValue); + $chain[] = sprintf('%s:element.%s.%s.%s.%s', $translationFile, $originalFormIdentifier, $propertyType, $property, $optionValue); + } + array_push($chain, ...$this->buildElementOptionKeys($translationFile, $formIdentifier, $elementIdentifier, $elementType, $propertyType, $property, $optionValue)); + } + return $chain; + } + + /** + * Builds the keychain for a validation error code on a regular form element. + * + * @param string[] $translationFiles + * @return list + */ + public function buildForValidationError( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + int $code, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.validation.error.%s.%s', $translationFile, $originalFormIdentifier, $elementIdentifier, $code); + $chain[] = sprintf('%s:%s.validation.error.%s', $translationFile, $originalFormIdentifier, $code); + } + array_push($chain, ...$this->buildValidationErrorKeys($translationFile, $formIdentifier, $elementIdentifier, $code)); + } + return $chain; + } + + /** + * Builds the keychain for a validation error code on the FormRuntime itself, + * where the original form identifier is used as the element segment. + * + * @param string[] $translationFiles + * @return list + */ + public function buildForFormRuntimeValidationError( + array $translationFiles, + string $formIdentifier, + string $elementIdentifier, + int $code, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.validation.error.%s.%s', $translationFile, $originalFormIdentifier, $originalFormIdentifier, $code); + $chain[] = sprintf('%s:validation.error.%s.%s', $translationFile, $originalFormIdentifier, $code); + $chain[] = sprintf('%s:%s.validation.error.%s', $translationFile, $originalFormIdentifier, $code); + } + array_push($chain, ...$this->buildValidationErrorKeys($translationFile, $formIdentifier, $elementIdentifier, $code)); + } + return $chain; + } + + /** + * Builds the keychain for a single finisher option. + * + * @param string[] $translationFiles + * @return list + */ + public function buildForFinisherOption( + array $translationFiles, + string $formIdentifier, + string $finisherIdentifier, + string $optionKey, + ?string $originalFormIdentifier + ): array { + $chain = []; + foreach ($translationFiles as $translationFile) { + if ($this->hasOriginalFormIdentifier($originalFormIdentifier)) { + $chain[] = sprintf('%s:%s.finisher.%s.%s', $translationFile, $originalFormIdentifier, $finisherIdentifier, $optionKey); + } + $chain[] = sprintf('%s:%s.finisher.%s.%s', $translationFile, $formIdentifier, $finisherIdentifier, $optionKey); + $chain[] = sprintf('%s:finisher.%s.%s', $translationFile, $finisherIdentifier, $optionKey); + } + return $chain; + } + + private function hasOriginalFormIdentifier(?string $originalFormIdentifier): bool + { + return is_string($originalFormIdentifier) && $originalFormIdentifier !== ''; + } + + /** + * @return list + */ + private function buildElementPropertyKeys( + string $translationFile, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property + ): array { + return [ + sprintf('%s:%s.element.%s.%s.%s', $translationFile, $formIdentifier, $elementIdentifier, $propertyType, $property), + sprintf('%s:element.%s.%s.%s', $translationFile, $elementIdentifier, $propertyType, $property), + sprintf('%s:element.%s.%s.%s', $translationFile, $elementType, $propertyType, $property), + ]; + } + + /** + * @return list + */ + private function buildElementOptionKeys( + string $translationFile, + string $formIdentifier, + string $elementIdentifier, + string $elementType, + string $propertyType, + string $property, + string|int $optionValue + ): array { + return [ + sprintf('%s:%s.element.%s.%s.%s.%s', $translationFile, $formIdentifier, $elementIdentifier, $propertyType, $property, $optionValue), + sprintf('%s:element.%s.%s.%s.%s', $translationFile, $elementIdentifier, $propertyType, $property, $optionValue), + sprintf('%s:element.%s.%s.%s.%s', $translationFile, $elementType, $propertyType, $property, $optionValue), + ]; + } + + /** + * @return list + */ + private function buildValidationErrorKeys( + string $translationFile, + string $formIdentifier, + string $elementIdentifier, + int $code + ): array { + return [ + sprintf('%s:%s.validation.error.%s.%s', $translationFile, $formIdentifier, $elementIdentifier, $code), + sprintf('%s:%s.validation.error.%s', $translationFile, $formIdentifier, $code), + sprintf('%s:validation.error.%s.%s', $translationFile, $elementIdentifier, $code), + sprintf('%s:validation.error.%s', $translationFile, $code), + ]; + } +} diff --git a/Classes/Domain/ValueObject/FormIdentifier.php b/Classes/Domain/ValueObject/FormIdentifier.php new file mode 100644 index 0000000..5424fb2 --- /dev/null +++ b/Classes/Domain/ValueObject/FormIdentifier.php @@ -0,0 +1,54 @@ +identifier; + } + + public function __toString(): string + { + return $this->toString(); + } +} diff --git a/Classes/Evaluation/EmailOrFormElementIdentifier.php b/Classes/Evaluation/EmailOrFormElementIdentifier.php new file mode 100644 index 0000000..c4af85e --- /dev/null +++ b/Classes/Evaluation/EmailOrFormElementIdentifier.php @@ -0,0 +1,43 @@ +prototypeName; + } + + public function getConfiguration(): array + { + return $this->configuration; + } + + public function setConfiguration(array $configuration): void + { + $this->configuration = $configuration; + } +} diff --git a/Classes/Event/AfterFormIsBuiltEvent.php b/Classes/Event/AfterFormIsBuiltEvent.php new file mode 100644 index 0000000..7d935c7 --- /dev/null +++ b/Classes/Event/AfterFormIsBuiltEvent.php @@ -0,0 +1,30 @@ + $options + */ + public function __construct( + private readonly FinisherContext $finisherContext, + private array $options + ) {} + + public function getFinisherContext(): FinisherContext + { + return $this->finisherContext; + } + + /** + * @return array + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * @param array $options + */ + public function setOptions(array $options): void + { + $this->options = $options; + } +} diff --git a/Classes/Event/BeforeFormIsCreatedEvent.php b/Classes/Event/BeforeFormIsCreatedEvent.php new file mode 100644 index 0000000..4583f1f --- /dev/null +++ b/Classes/Event/BeforeFormIsCreatedEvent.php @@ -0,0 +1,24 @@ +preventDeletion; + } +} diff --git a/Classes/Event/BeforeFormIsDuplicatedEvent.php b/Classes/Event/BeforeFormIsDuplicatedEvent.php new file mode 100644 index 0000000..9033336 --- /dev/null +++ b/Classes/Event/BeforeFormIsDuplicatedEvent.php @@ -0,0 +1,24 @@ +preventRemoval; + } +} diff --git a/Classes/Event/BeforeRenderableIsRenderedEvent.php b/Classes/Event/BeforeRenderableIsRenderedEvent.php new file mode 100644 index 0000000..7a2634c --- /dev/null +++ b/Classes/Event/BeforeRenderableIsRenderedEvent.php @@ -0,0 +1,32 @@ +getRow(); + if (($row['CType'] ?? '') !== 'form_formframework' || $event->getTableName() !== 'tt_content' || $event->getFieldName() !== 'pi_flexform') { + return; + } + $identifier = $event->getIdentifier(); + $currentFlexData = []; + if (!empty($row['pi_flexform']) && !is_array($row['pi_flexform'])) { + $currentFlexData = GeneralUtility::xml2array($row['pi_flexform']); + } + // Add selected form value + $identifier['ext-form-persistenceIdentifier'] = ''; + if (!empty($currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'])) { + $identifier['ext-form-persistenceIdentifier'] = $currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF']; + } + // Add bool - finisher override active or not + $identifier['ext-form-overrideFinishers'] = ''; + if (isset($currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF']) + && (int)$currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF'] === 1 + ) { + $identifier['ext-form-overrideFinishers'] = 'enabled'; + } + $event->setIdentifier($identifier); + } + + /** + * Adds the list of existing form definitions to the form selection drop down + * and adds sheets to override finisher settings if requested. + */ + #[AsEventListener('form-framework/modify-data-structure')] + public function modifyDataStructure(AfterFlexFormDataStructureParsedEvent $event): void + { + $identifier = $event->getIdentifier(); + if (!isset($identifier['ext-form-persistenceIdentifier'])) { + return; + } + $dataStructure = $event->getDataStructure(); + // We need $this->extbaseConfigurationManager to work at this point. This is directly needed as + // input for FormPersistenceManager, and indirectly for ConfigurationService. + // The ConfigurationManager of ext:form needs ext:extbase ConfigurationManager to retrieve basic TS + // settings (for "module.tx_form" allowed form storages). ConfigurationManager of extbase should *usually* + // only be called in extbase context and needs a Request, which is usually set by extbase bootstrap. + // We are however not in extbase context here. + // The solution is ugly, but at least makes the situation explicit: + // We fetch the request from $GLOBALS['TYPO3_REQUEST'] and actively fake a request in case this is not set. + // The latter may happen in CLI context, if FlexFormTools->parseDataStructureByIdentifier() is used by CLI (really?). + // @todo: There are various options to deal with this. First, the BE extbase ConfigurationManager could + // make the dependency to request optional. The fact that extbase BE functionality relies on FE TS + // is the main and long standing issue here. If that is possible, this event may not need to + // set the request anymore, and it would probably be enough for ext:form to rely on "global" and + // not page-id dependent TS. + // Secondly, the FlexFormTools data structure identifier stuff could be made request aware and + // could hand over a request to the event. DS identifier retrieval however is low-level and we + // may not want to have this dependency at all in this layer. + // Another option might be to make *this* part of ext:form extbase free and have an own TS + // layer to fetch TS that does not rely on current request. But that is something we may + // not want, either, since it may break too much? + if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface) { + $request = $GLOBALS['TYPO3_REQUEST']; + } else { + $request = (new ServerRequest())->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE); + } + $this->extbaseConfigurationManager->setRequest($request); + // @todo: Is this really needed? Isn't this event listener bound to BE only? + $isFrontend = false; + if (ApplicationType::fromRequest($request)->isFrontend()) { + $isFrontend = true; + } + $typoScriptSettings = $this->extbaseConfigurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $formSettings = $this->extFormConfigurationManager->getYamlConfiguration($typoScriptSettings, $isFrontend, $isFrontend ? $request : null); + try { + // Add list of existing forms to drop down if we find our key in the identifier + $formIsAccessible = false; + foreach ($this->formPersistenceManager->listForms($formSettings, new SearchCriteria()) as $formMetadata) { + if ($formMetadata->persistenceIdentifier === $identifier['ext-form-persistenceIdentifier']) { + $formIsAccessible = true; + } + if ($formMetadata->invalid) { + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['config']['items'][] = [ + 'label' => $formMetadata->name . ' (' . $formMetadata->persistenceIdentifier . ')', + 'value' => $formMetadata->persistenceIdentifier, + 'icon' => 'overlay-missing', + ]; + } else { + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['config']['items'][] = [ + 'label' => $formMetadata->name . ' (' . $formMetadata->persistenceIdentifier . ')', + 'value' => $formMetadata->persistenceIdentifier, + 'icon' => 'content-form', + ]; + } + } + if (!empty($identifier['ext-form-persistenceIdentifier']) && !$formIsAccessible) { + $languageService = $this->getLanguageService(); + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['config']['items'][] = [ + 'label' => sprintf( + $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.preview.inaccessiblePersistenceIdentifier'), + $identifier['ext-form-persistenceIdentifier'] + ), + 'value' => $identifier['ext-form-persistenceIdentifier'], + ]; + } + // If a specific form is selected and if finisher override is active, add finisher sheets + if (!empty($identifier['ext-form-persistenceIdentifier']) && $formIsAccessible) { + $persistenceIdentifier = $identifier['ext-form-persistenceIdentifier']; + $formDefinition = $this->formPersistenceManager->load($persistenceIdentifier); + $translationFile = 'LLL:EXT:form/Resources/Private/Language/Database.xlf'; + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.overrideFinishers'] = [ + 'label' => $translationFile . ':tt_content.pi_flexform.formframework.overrideFinishers', + 'onChange' => 'reload', + 'config' => [ + 'type' => 'check', + ], + ]; + $newSheets = []; + if (!empty($formDefinition['finishers'])) { + $prototypeName = $formDefinition['prototypeName'] ?? 'standard'; + $prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($prototypeName); + $newSheets = $this->getAdditionalFinisherSheets($persistenceIdentifier, $formDefinition, $prototypeName, $prototypeConfiguration); + } + if (empty($newSheets)) { + ArrayUtility::mergeRecursiveWithOverrule( + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.overrideFinishers'], + [ + 'description' => $translationFile . ':tt_content.pi_flexform.formframework.overrideFinishers.empty', + 'config' => [ + 'readOnly' => true, + ], + ] + ); + } + if ($identifier['ext-form-overrideFinishers'] === 'enabled') { + ArrayUtility::mergeRecursiveWithOverrule($dataStructure, $newSheets); + } + } + } catch (NoSuchFileException|ParseErrorException $e) { + $dataStructure = $this->addSelectedPersistenceIdentifier($identifier['ext-form-persistenceIdentifier'], $dataStructure); + $this->addInvalidFrameworkConfigurationFlashMessage($e, $identifier['ext-form-persistenceIdentifier']); + } + $event->setDataStructure($dataStructure); + } + + /** + * Returns additional flexform sheets with finisher fields + * + * @param string $persistenceIdentifier Current persistence identifier + * @param array $formDefinition The form definition + */ + protected function getAdditionalFinisherSheets(string $persistenceIdentifier, array $formDefinition, string $prototypeName, array $prototypeConfiguration): array + { + if (empty($prototypeConfiguration['finishersDefinition'])) { + return []; + } + $formIdentifier = $formDefinition['identifier']; + $finishersDefinition = $prototypeConfiguration['finishersDefinition']; + $sheets = ['sheets' => []]; + foreach ($formDefinition['finishers'] as $formFinisherDefinition) { + $finisherIdentifier = $formFinisherDefinition['identifier']; + if (!isset($finishersDefinition[$finisherIdentifier]['FormEngine']['elements'])) { + continue; + } + $sheetIdentifier = $this->buildFlexformSheetIdentifier($persistenceIdentifier, $prototypeName, $formIdentifier, $finisherIdentifier); + $finishersDefinition = $this->translateFinisherDefinitionByIdentifier($finisherIdentifier, $finishersDefinition, $prototypeConfiguration); + $prototypeFinisherDefinition = $finishersDefinition[$finisherIdentifier]; + $finisherLabel = $prototypeFinisherDefinition['FormEngine']['label'] ?? ''; + $sheet = $this->initializeNewSheetArray($sheetIdentifier, $finisherLabel); + $converterDto = GeneralUtility::makeInstance(ProcessorDto::class, $finisherIdentifier, $prototypeFinisherDefinition, $formFinisherDefinition); + // Remove all container elements "el" from sections beforehand. + // These should not be matched by the regex below. This greatly reduces headaches. + $elements = $prototypeFinisherDefinition['FormEngine']['elements']; + foreach ($elements as $key => $element) { + if ($element['section'] ?? false) { + unset($elements[$key]['el']); + } + } + // Iterate over all `prototypes..finishersDefinition..FormEngine.elements` + // values and convert them to FlexForm elements. + GeneralUtility::makeInstance(ArrayProcessor::class, $elements)->forEach( + GeneralUtility::makeInstance( + ArrayProcessing::class, + 'convertToFlexFormSheets', + // Parse top level elements and section containers. + '^(.*)(?:\.config\.type|\.section)$', + GeneralUtility::makeInstance(FinisherOptionGenerator::class, $converterDto) + ) + ); + $sheet[$sheetIdentifier]['ROOT']['el'] = $converterDto->getResult(); + ArrayUtility::mergeRecursiveWithOverrule($sheets['sheets'], $sheet); + } + return $sheets; + } + + /** + * Boilerplate XML array of a new sheet. + */ + protected function initializeNewSheetArray(string $sheetIdentifier, string $finisherName): array + { + if (empty($sheetIdentifier)) { + throw new \InvalidArgumentException('$sheetIdentifier must not be empty.', 1472060918); + } + if (empty($finisherName)) { + throw new \InvalidArgumentException('$finisherName must not be empty.', 1472060919); + } + return [ + $sheetIdentifier => [ + 'ROOT' => [ + 'sheetTitle' => $finisherName, + 'type' => 'array', + 'el' => [], + ], + ], + ]; + } + + protected function addSelectedPersistenceIdentifier(string $persistenceIdentifier, array $dataStructure): array + { + if (!empty($persistenceIdentifier)) { + $languageService = $this->getLanguageService(); + $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['config']['items'][] = [ + 'label' => sprintf( + $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.preview.inaccessiblePersistenceIdentifier'), + $persistenceIdentifier + ), + 'value' => $persistenceIdentifier, + ]; + } + return $dataStructure; + } + + protected function addInvalidFrameworkConfigurationFlashMessage(\Exception $e, string $identifier = ''): void + { + $languageService = $this->getLanguageService(); + $this->flashMessageService + ->getMessageQueueByIdentifier('core.template.flashMessages') + ->enqueue( + new FlashMessage( + sprintf( + $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.preview.invalidFrameworkConfiguration.text'), + $identifier, + $e->getMessage() + ), + $languageService->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.preview.invalidFrameworkConfiguration.title'), + ContextualFeedbackSeverity::ERROR, + true + ) + ); + } + + protected function buildFlexformSheetIdentifier(string $persistenceIdentifier, string $prototypeName, string $formIdentifier, string $finisherIdentifier): string + { + return md5($persistenceIdentifier . $prototypeName . $formIdentifier . $finisherIdentifier); + } + + protected function translateFinisherDefinitionByIdentifier(string $finisherIdentifier, array $finishersDefinition, array $prototypeConfiguration): array + { + $translationFiles = $finishersDefinition[$finisherIdentifier]['FormEngine']['translationFiles'] ?? $prototypeConfiguration['formEngine']['translationFiles']; + $finishersDefinition[$finisherIdentifier]['FormEngine'] = $this->translationService->translateValuesRecursive( + $finishersDefinition[$finisherIdentifier]['FormEngine'], + $translationFiles + ); + return $finishersDefinition; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/EventListener/FormatDateRenderableBeforeRendering.php b/Classes/EventListener/FormatDateRenderableBeforeRendering.php new file mode 100644 index 0000000..b30e606 --- /dev/null +++ b/Classes/EventListener/FormatDateRenderableBeforeRendering.php @@ -0,0 +1,93 @@ +renderable; + if ($renderable->getType() !== 'Date') { + return; + } + + $date = $event->formRuntime[$renderable->getIdentifier()]; + if ($date instanceof \DateTime) { + // @see https://www.w3.org/TR/2011/WD-html-markup-20110405/input.date.html#input.date.attrs.value + // 'Y-m-d' = https://tools.ietf.org/html/rfc3339#section-5.6 -> full-date + $event->formRuntime[$renderable->getIdentifier()] = $date->format('Y-m-d'); + } elseif (is_string($date) && $date !== '' && !$this->isAbsoluteDate($date)) { + // Resolve relative date expressions used as defaultValue (e.g. "today", "+1 day") + $resolved = $this->parseRelativeDate($date); + if ($resolved !== null) { + $event->formRuntime[$renderable->getIdentifier()] = $resolved->format('Y-m-d'); + } + } + + if ($renderable instanceof FormElementInterface) { + $this->resolveRelativeDateAttributes($renderable); + } + } + + /** + * Resolve relative date expressions in the HTML min/max attributes to absolute Y-m-d format. + * + * The HTML5 element requires min/max values in RFC 3339 full-date + * format (Y-m-d). When a form definition uses relative expressions like "today" or + * "-18 years", these must be resolved to absolute dates before rendering. + */ + private function resolveRelativeDateAttributes(FormElementInterface $renderable): void + { + $properties = $renderable->getProperties(); + $fluidAttributes = $properties['fluidAdditionalAttributes'] ?? []; + + $resolved = false; + foreach (['min', 'max'] as $attribute) { + $value = $fluidAttributes[$attribute] ?? ''; + if ($value === '' || $this->isAbsoluteDate($value)) { + continue; + } + + $date = $this->parseRelativeDate($value); + if ($date !== null) { + $fluidAttributes[$attribute] = $date->format('Y-m-d'); + $resolved = true; + } + } + + if ($resolved) { + $renderable->setProperty('fluidAdditionalAttributes', $fluidAttributes); + } + } + + private function isAbsoluteDate(string $value): bool + { + return (bool)preg_match(DateRangeValidatorPatterns::RFC3339_FULL_DATE_PCRE, $value); + } + + private function parseRelativeDate(string $value): ?\DateTime + { + return DateRangeValidatorPatterns::parseRelativeDateExpression($value); + } +} diff --git a/Classes/EventListener/ModifyFormDefinitionRecordActionsEventListener.php b/Classes/EventListener/ModifyFormDefinitionRecordActionsEventListener.php new file mode 100644 index 0000000..b66a23b --- /dev/null +++ b/Classes/EventListener/ModifyFormDefinitionRecordActionsEventListener.php @@ -0,0 +1,93 @@ +getRecord()->getMainType() !== FormDefinitionRepository::TABLE_NAME) { + return; + } + + $uid = $event->getRecord()->getUid(); + $formPersistenceIdentifier = (string)$uid; + + // Replace the "edit" action with a link to the Form Editor + if ($event->hasAction('edit', ActionGroup::primary)) { + $returnUrl = (string)$event->getRecordList()->listURL(); + $editUrl = (string)$this->uriBuilder->buildUriFromRoute('form_editor', [ + 'formPersistenceIdentifier' => $formPersistenceIdentifier, + 'returnUrl' => $returnUrl, + ]); + + $editButton = $this->componentFactory->createLinkButton() + ->setIcon($this->iconFactory->getIcon('actions-open', IconSize::SMALL)) + ->setTitle($GLOBALS['LANG']->sL('core.mod_web_list:edit')) + ->setHref($editUrl); + + $event->setAction($editButton, 'edit', ActionGroup::primary); + } + + // The “delete” action is being removed because references in the FlexForm are not taken into account + // (no warning is displayed). + $event->removeAction('delete', ActionGroup::primary); + } + + /** + * The “edit” action is being removed, as it is not possible to edit multiple forms simultaneously. + * The form editor should always be used for editing. + * The “delete” action is being removed because references in the FlexForm are not taken into account + * (no warning is displayed). + */ + #[AsEventListener('form-framework/modify-form-definition-record-list-table-actions', method: 'modifyRecordListTableActions')] + public function modifyRecordListTableActions(ModifyRecordListTableActionsEvent $event): void + { + if ($event->getTable() !== FormDefinitionRepository::TABLE_NAME) { + return; + } + $event->removeAction('edit'); + $event->removeAction('delete'); + } +} diff --git a/Classes/EventListener/ModifyFormDefinitionRecordListRowEventListener.php b/Classes/EventListener/ModifyFormDefinitionRecordListRowEventListener.php new file mode 100644 index 0000000..a692676 --- /dev/null +++ b/Classes/EventListener/ModifyFormDefinitionRecordListRowEventListener.php @@ -0,0 +1,68 @@ +getTable() !== FormDefinitionRepository::TABLE_NAME) { + return; + } + + $data = $event->getData(); + + if (!isset($data['__label'])) { + return; + } + + $uid = $event->getRecord()->getUid(); + $formPersistenceIdentifier = (string)$uid; + + $returnUrl = (string)$event->getRecordList()->listURL(); + $editUrl = (string)$this->uriBuilder->buildUriFromRoute('form_editor', [ + 'formPersistenceIdentifier' => $formPersistenceIdentifier, + 'returnUrl' => $returnUrl, + ]); + + $data['__label'] = preg_replace( + '/href="[^"]*"/', + 'href="' . htmlspecialchars($editUrl) . '"', + $data['__label'] + ); + + $event->setData($data); + } +} diff --git a/Classes/EventListener/ProcessFileListActionsEventListener.php b/Classes/EventListener/ProcessFileListActionsEventListener.php new file mode 100644 index 0000000..a402312 --- /dev/null +++ b/Classes/EventListener/ProcessFileListActionsEventListener.php @@ -0,0 +1,48 @@ +isFile() || !$event->getResource() instanceof AbstractFile) { + return; + } + $fullIdentifier = $event->getResource()->getCombinedIdentifier(); + if (!str_ends_with($fullIdentifier, FormPersistenceManagerInterface::FORM_DEFINITION_FILE_EXTENSION)) { + return; + } + + foreach (self::DISABLED_ACTIONS as $disableIconName) { + $event->removeAction($disableIconName); + } + } +} diff --git a/Classes/EventListener/TranslateDefaultValueBeforeRendering.php b/Classes/EventListener/TranslateDefaultValueBeforeRendering.php new file mode 100644 index 0000000..1887f2d --- /dev/null +++ b/Classes/EventListener/TranslateDefaultValueBeforeRendering.php @@ -0,0 +1,65 @@ +renderable; + if (!$renderable instanceof FormElementInterface) { + return; + } + $originalDefaultValue = $renderable->getDefaultValue(); + if ($originalDefaultValue === null) { + return; + } + // Array defaultValues (e.g. MultiCheckbox pre-selections) contain option keys, not + // human-readable labels. Translating them would break the value-to-option mapping. + // The option labels themselves are translated via properties.options.[*] instead. + if (is_array($originalDefaultValue)) { + return; + } + try { + $translatedDefaultValue = $this->translationService->translateFormElementValue( + $renderable, + ['defaultValue'], + $event->formRuntime, + ); + } catch (\Throwable) { + // Translation may fail if site/language configuration is not available in the request. + return; + } + if ($translatedDefaultValue !== null && $translatedDefaultValue !== $originalDefaultValue) { + $renderable->setDefaultValue($translatedDefaultValue); + } + } +} diff --git a/Classes/EventListener/ValidateAdvancedPasswordRenderable.php b/Classes/EventListener/ValidateAdvancedPasswordRenderable.php new file mode 100644 index 0000000..a4c6fd1 --- /dev/null +++ b/Classes/EventListener/ValidateAdvancedPasswordRenderable.php @@ -0,0 +1,56 @@ +renderable; + if ($renderable->getType() !== 'AdvancedPassword') { + return; + } + if (!$renderable instanceof AbstractRenderable) { + return; + } + + $elementValue = $event->value; + if ($elementValue['password'] !== $elementValue['confirmation']) { + $processingRule = $renderable->getRootForm()->getProcessingRule($renderable->getIdentifier()); + $processingRule->getProcessingMessages()->addError( + new Error( + $this->translationService->translate('validation.error.1556283177', null, 'EXT:form/Resources/Private/Language/locallang.xlf'), + 1556283177 + ) + ); + } + $event->value = $elementValue['password']; + } + +} diff --git a/Classes/Exception.php b/Classes/Exception.php new file mode 100644 index 0000000..b8c2d05 --- /dev/null +++ b/Classes/Exception.php @@ -0,0 +1,25 @@ +|null $incomingFieldArray + * @param-out array|null $incomingFieldArray + */ + public function processDatamap_preProcessFieldArray( + ?array &$incomingFieldArray, + string $table, + string|int $id, + DataHandler $dataHandler, + ): void { + if ($table !== 'form_definition') { + return; + } + + $isUpdate = MathUtility::canBeInterpretedAsInteger($id); + $command = $isUpdate + ? FormDefinitionPersistenceCommand::Update + : FormDefinitionPersistenceCommand::Create; + $recordIdentifier = $isUpdate ? (int)$id : (string)$id; + + if (!$this->guard->isInvocationAllowed($command, $recordIdentifier, $incomingFieldArray)) { + $incomingFieldArray = null; + $dataHandler->log( + $table, + $isUpdate ? (int)$id : 0, + $isUpdate ? SystemLogDatabaseAction::UPDATE : SystemLogDatabaseAction::INSERT, + null, + SystemLogErrorClassification::USER_ERROR, + 'Persisting form definition "%s" via DataHandler is denied', + null, + [$id], + ); + return; + } + + $this->guard->consumeInvocation($command, $recordIdentifier, $incomingFieldArray); + } + + /** + * Blocks unauthorised delete commands on form_definition records. + * + * Sets $commandIsProcessed to true (preventing DataHandler's built-in + * delete) when no COMMAND_FORM_DELETE grant is pending. This mirrors the + * FilePersistenceSlot pattern for FAL-based form definitions. + */ + public function processCmdmap( + string $command, + string $table, + int|string $id, + mixed $value, + bool &$commandIsProcessed, + DataHandler $dataHandler, + ): void { + if ($table !== 'form_definition' || $command !== 'delete') { + return; + } + + if (!$this->guard->isInvocationAllowed(FormDefinitionPersistenceCommand::Delete, (int)$id)) { + $commandIsProcessed = true; + $dataHandler->log( + $table, + (int)$id, + SystemLogDatabaseAction::DELETE, + null, + SystemLogErrorClassification::USER_ERROR, + 'Deleting form definition "%s" via DataHandler is denied', + null, + [$id], + ); + return; + } + + $this->guard->consumeInvocation(FormDefinitionPersistenceCommand::Delete, (int)$id); + } +} diff --git a/Classes/Hooks/FormFileProvider.php b/Classes/Hooks/FormFileProvider.php new file mode 100644 index 0000000..ee89378 --- /dev/null +++ b/Classes/Hooks/FormFileProvider.php @@ -0,0 +1,89 @@ +identifier, FormPersistenceManagerInterface::FORM_DEFINITION_FILE_EXTENSION); + } + + public function addItems(array $items): array + { + $this->initialize(); + return $this->purgeItems($items); + } + + /** + * Purges items that are not allowed for according command. + * According canBeEdited, canBeRenamed, ... commands will always return + * false in order to remove those form file items. + * + * Using the canRender() approach avoid adding hardcoded index name + * lookup. Thus, it's streamlined with the rest of the provides, but + * actually purges items instead of adding them. + * + * @param array $items + */ + protected function purgeItems(array $items): array + { + foreach ($items as $name => $item) { + $type = $item['type']; + + if ($type === 'submenu' && !empty($item['childItems'])) { + $item['childItems'] = $this->purgeItems($item['childItems']); + } elseif (!$this->canRender($name, $type)) { + unset($items[$name]); + } + } + + return $items; + } + + protected function canBeEdited(): bool + { + return false; + } + + protected function canBeRenamed(): bool + { + return false; + } +} diff --git a/Classes/Hooks/ImportExportHook.php b/Classes/Hooks/ImportExportHook.php new file mode 100644 index 0000000..cdc3361 --- /dev/null +++ b/Classes/Hooks/ImportExportHook.php @@ -0,0 +1,39 @@ +allowInvocation( + FilePersistenceSlot::COMMAND_FILE_ADD, + implode(':', [$fileRecord['storage'], $fileRecord['identifier']]), + $filePersistenceSlot->getContentSignature(file_get_contents($temporaryFile)) + ); + } +} diff --git a/Classes/Mvc/Configuration/ConfigurationManager.php b/Classes/Mvc/Configuration/ConfigurationManager.php new file mode 100644 index 0000000..436f5bf --- /dev/null +++ b/Classes/Mvc/Configuration/ConfigurationManager.php @@ -0,0 +1,140 @@ +/ directory (see {@see \TYPO3\CMS\Form\DependencyInjection\FormYamlCollectorConfigurator}). + * + * Scope: frontend / backend + * @internal + */ +#[AsAlias(ConfigurationManagerInterface::class, public: true)] +readonly class ConfigurationManager implements ExtFormConfigurationManagerInterface +{ + public function __construct( + private YamlSource $yamlSource, + #[Autowire(service: 'cache.assets')] + private FrontendInterface $cache, + private TypoScriptService $typoScriptService, + private FormYamlCollector $formYamlCollector, + ) {} + + /** + * Load and parse YAML files for the current rendering context. + * + * Files are resolved via auto-discovery: {@see FormYamlCollector} scans every + * active extension's Configuration/Form// directory and returns + * all paths sorted by priority. + * + * The following post-processing steps are applied to the merged configuration: + * + * * Remove all keys whose values are NULL + * * Sort by array keys if all keys within a nesting level are numerical + * * Resolve possible TypoScript settings in FE mode + */ + public function getYamlConfiguration(array $typoScriptSettings, bool $isFrontend, ?ServerRequestInterface $request = null): array + { + $yamlSettingsFilePaths = $this->formYamlCollector->getPaths(); + $cacheKey = strtolower('YamlSettings_form' . md5(json_encode($yamlSettingsFilePaths))); + if ($this->cache->has($cacheKey)) { + $yamlSettings = $this->cache->get($cacheKey); + } else { + $yamlSettings = $this->yamlSource->load($yamlSettingsFilePaths); + $yamlSettings = ArrayUtility::removeNullValuesRecursive($yamlSettings); + $yamlSettings = ArrayUtility::sortArrayWithIntegerKeysRecursive($yamlSettings); + $this->cache->set($cacheKey, $yamlSettings); + } + + $this->applySiteSettingsOverrides($yamlSettings, $request); + + if (is_array($typoScriptSettings['yamlSettingsOverrides'] ?? null) && !empty($typoScriptSettings['yamlSettingsOverrides'])) { + $yamlSettingsOverrides = $typoScriptSettings['yamlSettingsOverrides']; + if ($isFrontend) { + if ($request === null) { + throw new \RuntimeException('Frontend rendering an ext:form requires the request being hand over', 1760451538); + } + $yamlSettingsOverrides = $this->typoScriptService->resolvePossibleTypoScriptConfiguration($yamlSettingsOverrides, $request); + } + ArrayUtility::mergeRecursiveWithOverrule($yamlSettings, $yamlSettingsOverrides); + } + return $yamlSettings; + } + + /** + * Read form template/translation site set settings from the current site + * and merge them into the YAML configuration. + * Non-empty values are added at key 20 so they overlay the base paths (key 10) + * while still allowing higher-priority overrides from form sets or yamlSettingsOverrides. + */ + private function applySiteSettingsOverrides(array &$yamlSettings, ?ServerRequestInterface $request): void + { + $site = $request?->getAttribute('site'); + if (!$site instanceof Site) { + return; + } + + $siteSettings = $site->getSettings(); + $renderingOptionsOverrides = []; + + $templateRootPath = (string)$siteSettings->get('form.templates.templateRootPath', ''); + if ($templateRootPath !== '') { + $renderingOptionsOverrides['templateRootPaths'][20] = $templateRootPath; + } + + $partialRootPath = (string)$siteSettings->get('form.templates.partialRootPath', ''); + if ($partialRootPath !== '') { + $renderingOptionsOverrides['partialRootPaths'][20] = $partialRootPath; + } + + $layoutRootPath = (string)$siteSettings->get('form.templates.layoutRootPath', ''); + if ($layoutRootPath !== '') { + $renderingOptionsOverrides['layoutRootPaths'][20] = $layoutRootPath; + } + + $translationFile = (string)$siteSettings->get('form.translation.translationFile', ''); + if ($translationFile !== '') { + $renderingOptionsOverrides['translation']['translationFiles'][20] = $translationFile; + } + + if ($renderingOptionsOverrides !== []) { + $overrides = [ + 'prototypes' => [ + 'standard' => [ + 'formElementsDefinition' => [ + 'Form' => [ + 'renderingOptions' => $renderingOptionsOverrides, + ], + ], + ], + ], + ]; + ArrayUtility::mergeRecursiveWithOverrule($yamlSettings, $overrides); + } + } +} diff --git a/Classes/Mvc/Configuration/ConfigurationManagerInterface.php b/Classes/Mvc/Configuration/ConfigurationManagerInterface.php new file mode 100644 index 0000000..bf64665 --- /dev/null +++ b/Classes/Mvc/Configuration/ConfigurationManagerInterface.php @@ -0,0 +1,29 @@ +/ + * with an accompanying config.yaml that declares name, label and priority. + * The collector is populated by {@see \TYPO3\CMS\Form\DependencyInjection\FormYamlCollectorConfigurator} + * and provides a priority-sorted list of file paths to {@see ConfigurationManager}. + * + * @internal + */ +final class FormYamlCollector +{ + /** @var list */ + private array $configurations = []; + + public function add(FormYamlConfiguration $configuration): void + { + $this->configurations[] = $configuration; + } + + /** + * Returns all registered file paths sorted by ascending priority + * (lower = loaded first = acts as base, higher = override). + * + * @return list + */ + public function getPaths(): array + { + $sorted = $this->configurations; + usort($sorted, static fn(FormYamlConfiguration $a, FormYamlConfiguration $b): int => $a->priority <=> $b->priority); + + return array_values(array_map( + static fn(FormYamlConfiguration $c): string => $c->path, + $sorted + )); + } + + /** + * Returns all registered configurations, regardless of priority. + * Useful for diagnostic/debug purposes. + * + * @return list + */ + public function getAllConfigurations(): array + { + return array_values($this->configurations); + } +} diff --git a/Classes/Mvc/Configuration/FormYamlConfiguration.php b/Classes/Mvc/Configuration/FormYamlConfiguration.php new file mode 100644 index 0000000..45be8ee --- /dev/null +++ b/Classes/Mvc/Configuration/FormYamlConfiguration.php @@ -0,0 +1,47 @@ +coreTypoScriptService->convertPlainArrayToTypoScriptArray($configuration); + $contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class); + $contentObjectRenderer->setRequest($request); + // @todo: Setting request to COR is probably important, but setting page record here *may* not be needed in this case? + $contentObjectRenderer->start($request->getAttribute('frontend.page.information')->getPageRecord(), 'pages'); + $configuration = $this->resolveTypoScriptConfiguration($configuration, $contentObjectRenderer); + return $this->coreTypoScriptService->convertTypoScriptArrayToPlainArray($configuration); + } + + /** + * Parse a configuration with ContentObjectRenderer::cObjGetSingle() + * if there is an array key without and with a dot at the end. + * This sample would be identified as a TypoScript parsable configuration + * part: + * + * [ + * 'example' => 'TEXT' + * 'example.' => [ + * 'value' => 'some value' + * ] + * ] + */ + protected function resolveTypoScriptConfiguration(array $configuration, ContentObjectRenderer $contentObjectRenderer): array + { + foreach ($configuration as $key => $value) { + $keyWithoutDot = rtrim((string)$key, '.'); + if (isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) { + $value = $contentObjectRenderer->cObjGetSingle( + $configuration[$keyWithoutDot], + $configuration[$keyWithoutDot . '.'], + $keyWithoutDot + ); + $configuration[$keyWithoutDot] = $value; + } elseif (!isset($configuration[$keyWithoutDot]) && isset($configuration[$keyWithoutDot . '.'])) { + $configuration[$keyWithoutDot] = $this->resolveTypoScriptConfiguration($value, $contentObjectRenderer); + } + unset($configuration[$keyWithoutDot . '.']); + } + return $configuration; + } +} diff --git a/Classes/Mvc/Configuration/YamlSource.php b/Classes/Mvc/Configuration/YamlSource.php new file mode 100644 index 0000000..bc8617d --- /dev/null +++ b/Classes/Mvc/Configuration/YamlSource.php @@ -0,0 +1,196 @@ +loadFromFile($fileToLoad); + } else { + $loadedConfiguration = $this->loadFromFilePath($fileToLoad); + if (isset($loadedConfiguration['TYPO3']['CMS']['Form'])) { + $namespacedConfiguration = $loadedConfiguration['TYPO3']['CMS']['Form']; + unset($loadedConfiguration['TYPO3']); + $loadedConfiguration = array_replace_recursive($namespacedConfiguration, $loadedConfiguration); + } + } + $configuration = array_replace_recursive($configuration, $loadedConfiguration); + } + return ArrayUtility::convertBooleanStringsToBooleanRecursive($configuration); + } + + /** + * Save the specified configuration array to the given file in YAML format. + * + * @param File|string $fileToSave The file to write to. + * @param array $configuration The configuration to save + * @throws FileWriteException if the file could not be written + * @internal + */ + public function save(File|string $fileToSave, array $configuration): void + { + try { + $header = $this->getHeaderFromFile($fileToSave); + } catch (InsufficientFileAccessPermissionsException $e) { + throw new FileWriteException($e->getMessage(), 1512584488, $e); + } + + $yaml = Yaml::dump($configuration, 99, 2); + + if ($fileToSave instanceof File) { + // @deprecated: Remove in v16 along with the FileFormsToDatabaseUpgradeWizard + try { + $this->filePersistenceSlot->allowInvocation( + FilePersistenceSlot::COMMAND_FILE_SET_CONTENTS, + $this->buildCombinedIdentifier( + $fileToSave->getParentFolder(), + $fileToSave->getName() + ), + $this->filePersistenceSlot->getContentSignature( + $header . LF . $yaml + ) + ); + $fileToSave->setContents($header . LF . $yaml); + } catch (InsufficientFileAccessPermissionsException $e) { + throw new FileWriteException($e->getMessage(), 1512582753, $e); + } + } else { + $byteCount = @file_put_contents($fileToSave, $header . LF . $yaml); + if ($byteCount === false) { + $error = error_get_last(); + $errorMessage = $error['message'] ?? 'Check that the file exists and can be written.'; + throw new FileWriteException($errorMessage, 1512582929); + } + } + } + + /** + * Load YAML configuration from a local file path + * + * @throws ParseErrorException + */ + protected function loadFromFilePath(string $filePath): array + { + try { + $loadedConfiguration = $this->yamlFileLoader->load($filePath); + } catch (\RuntimeException $e) { + throw new ParseErrorException( + sprintf('An error occurred while parsing file "%s": %s', $filePath, $e->getMessage()), + 1480195405, + $e + ); + } + return $loadedConfiguration; + } + + /** + * Load YAML configuration from a FAL file + * + * @throws ParseErrorException + */ + protected function loadFromFile(File $file): array + { + $fileIdentifier = $file->getIdentifier(); + $rawYamlContent = $file->getContents(); + try { + $loadedConfiguration = Yaml::parse($rawYamlContent); + } catch (ParseException $e) { + throw new ParseErrorException( + sprintf('An error occurred while parsing file "%s": %s', $fileIdentifier, $e->getMessage()), + 1574422322, + $e + ); + } + return $loadedConfiguration; + } + + /** + * Read the header part from the given file. That means, every line + * until the first non comment line is found. + * + * @return string The header of the given YAML file + */ + protected function getHeaderFromFile(File|string $file): string + { + $header = ''; + if ($file instanceof File) { + $fileLines = explode(LF, $file->getContents()); + } elseif (is_file($file)) { + $fileLines = file($file); + } else { + return ''; + } + foreach ($fileLines as $line) { + if (str_starts_with($line, '#')) { + $header .= $line; + } else { + break; + } + } + return $header; + } + + /* + * @deprecated: Remove in v16 along with the FileFormsToDatabaseUpgradeWizard + */ + protected function buildCombinedIdentifier(FolderInterface $folder, string $fileName): string + { + return sprintf( + '%d:%s%s', + $folder->getStorage()->getUid(), + $folder->getIdentifier(), + $fileName + ); + } +} diff --git a/Classes/Mvc/Persistence/Event/AfterFormDefinitionLoadedEvent.php b/Classes/Mvc/Persistence/Event/AfterFormDefinitionLoadedEvent.php new file mode 100644 index 0000000..59c1ad3 --- /dev/null +++ b/Classes/Mvc/Persistence/Event/AfterFormDefinitionLoadedEvent.php @@ -0,0 +1,50 @@ +formDefinition; + } + + public function setFormDefinition(array $formDefinition): void + { + $this->formDefinition = $formDefinition; + } + + public function getPersistenceIdentifier(): string + { + return $this->persistenceIdentifier; + } + + public function getCacheKey(): string + { + return $this->cacheKey; + } +} diff --git a/Classes/Mvc/Persistence/Exception.php b/Classes/Mvc/Persistence/Exception.php new file mode 100644 index 0000000..7af5f3e --- /dev/null +++ b/Classes/Mvc/Persistence/Exception.php @@ -0,0 +1,27 @@ +runtimeCache->has($cacheKey)) { + $formDefinition = $this->runtimeCache->get($cacheKey); + } else { + $formDefinition = $this->loadFromStorage($persistenceIdentifier, $request); + $this->runtimeCache->set($cacheKey, $formDefinition); + } + + $formDefinition = $this->eventDispatcher + ->dispatch(new AfterFormDefinitionLoadedEvent($formDefinition, $persistenceIdentifier, $cacheKey)) + ->getFormDefinition(); + + if ($request !== null && !empty($typoScriptSettings['formDefinitionOverrides'][$formDefinition['identifier']] ?? null)) { + $formDefinitionOverrides = $this->typoScriptService->resolvePossibleTypoScriptConfiguration( + $typoScriptSettings['formDefinitionOverrides'][$formDefinition['identifier']], + $request + ); + ArrayUtility::mergeRecursiveWithOverrule($formDefinition, $formDefinitionOverrides); + } + + return $formDefinition; + } + + /** + * Save form definition to appropriate storage + * + * @throws PersistenceManagerException + */ + public function save(string $persistenceIdentifier, array $formDefinition, array $formSettings, ?string $storageLocation = null): FormIdentifier + { + if (!$this->isAllowedPersistenceIdentifier($persistenceIdentifier)) { + throw new PersistenceManagerException( + sprintf('Save to path "%s" is not allowed.', $persistenceIdentifier), + 1477680881 + ); + } + + $identifier = new FormIdentifier($persistenceIdentifier); + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($persistenceIdentifier); + $formData = FormData::fromArray($formDefinition); + + $context = null; + if (MathUtility::canBeInterpretedAsInteger($storageLocation)) { + $context = StorageContext::create((int)$storageLocation); + } + + $savedIdentifier = $adapter->write($identifier, $formData, $context); + + $this->clearFormCache($savedIdentifier->identifier); + return $savedIdentifier; + } + + /** + * Delete form definition from storage + */ + public function delete(string $persistenceIdentifier, array $formSettings): void + { + $identifier = new FormIdentifier($persistenceIdentifier); + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($persistenceIdentifier); + + if (!$adapter->exists($identifier)) { + throw new PersistenceManagerException( + sprintf('The form "%s" does not exist.', $persistenceIdentifier), + 1472239535 + ); + } + + $adapter->delete($identifier); + $this->clearFormCache($persistenceIdentifier); + } + + /** + * List all form definitions from all available storages + */ + public function listForms(array $formSettings, SearchCriteria $searchCriteria): array + { + $identifiers = []; + $forms = []; + + foreach ($this->storageAdapterFactory->getAllAdapters() as $adapter) { + try { + $formDataList = $adapter->findAll($searchCriteria); + + foreach ($formDataList as $formData) { + if ($formData->storageType === null) { + $formData = $formData->withStorageType($adapter->getTypeIdentifier()); + } + $forms[] = $formData; + if (!isset($identifiers[$formData->identifier])) { + $identifiers[$formData->identifier] = 0; + } + $identifiers[$formData->identifier]++; + } + } catch (\Exception $e) { + continue; + } + } + + foreach ($identifiers as $identifier => $count) { + if ($count > 1) { + foreach ($forms as $index => $formMetadata) { + if ($formMetadata->identifier === $identifier) { + $forms[$index] = $formMetadata->withDuplicateIdentifier(true); + } + } + } + } + + $allReferencesForFileUid = $this->databaseService->getAllReferencesForFileUid(); + $allReferencesForPersistenceIdentifier = $this->databaseService->getAllReferencesForPersistenceIdentifier(); + $allReferencesForFormDefinitionUid = $this->databaseService->getAllReferencesForFormDefinitionUid(); + + foreach ($forms as $index => $formMetadata) { + if (isset($formMetadata->fileUid) && array_key_exists($formMetadata->fileUid, $allReferencesForFileUid)) { + $referenceCount = $allReferencesForFileUid[$formMetadata->fileUid]; + } elseif ($formMetadata->persistenceIdentifier && array_key_exists($formMetadata->persistenceIdentifier, $allReferencesForFormDefinitionUid)) { + $referenceCount = $allReferencesForFormDefinitionUid[$formMetadata->persistenceIdentifier]; + } elseif ($formMetadata->persistenceIdentifier && array_key_exists($formMetadata->persistenceIdentifier, $allReferencesForPersistenceIdentifier)) { + $referenceCount = $allReferencesForPersistenceIdentifier[$formMetadata->persistenceIdentifier]; + } else { + $referenceCount = 0; + } + if ($referenceCount > 0) { + $forms[$index] = $formMetadata->withReferenceCount($referenceCount); + } + } + + return $this->sortForms($forms, $formSettings, $searchCriteria->getOrderField(), $searchCriteria->getOrderDirection()); + } + + /** + * Check if any forms are available + */ + public function hasForms(array $formSettings): bool + { + foreach ($this->storageAdapterFactory->getAllAdapters() as $adapter) { + try { + $forms = $adapter->findAll(new SearchCriteria(limit: 1)); + + if (!empty($forms)) { + return true; + } + } catch (\Exception) { + continue; + } + } + + return false; + } + + /** + * Get unique persistence identifier for a new form + */ + public function getUniquePersistenceIdentifier(string $storage, string $formIdentifier, ?string $savePath): string + { + return $this->storageAdapterFactory->getAdapterByType($storage)->getUniquePersistenceIdentifier($formIdentifier, $savePath); + } + + /** + * Get unique identifier (not persistence identifier) + */ + public function getUniqueIdentifier(string $identifier): string + { + $originalIdentifier = $identifier; + + if ($this->checkForDuplicateIdentifier($identifier)) { + for ($attempts = 1; $attempts < 100; $attempts++) { + $identifier = sprintf('%s_%d', $originalIdentifier, $attempts); + if (!$this->checkForDuplicateIdentifier($identifier)) { + return $identifier; + } + } + + $identifier = $originalIdentifier . '_' . time(); + if ($this->checkForDuplicateIdentifier($identifier)) { + throw new NoUniqueIdentifierException( + sprintf('Could not find a unique identifier for form identifier "%s" after %d attempts', $identifier, $attempts), + 1477688567 + ); + } + } + + return $identifier; + } + + /** + * Check if a storage location is allowed + * + * For database storage: storageLocation is a PID + * For file storage: storageLocation is a folder path (e.g., "1:/forms/") + */ + public function isAllowedStorageLocation(string $storageLocation): bool + { + try { + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($storageLocation); + return $adapter->isAllowedStorageLocation($storageLocation); + } catch (\Exception) { + return false; + } + } + + /** + * Check if a persistence identifier is allowed + * + * For database storage: identifier is a UID or NEW* + * For file storage: identifier is a full file path (e.g., "1:/forms/contact.form.yaml") + */ + public function isAllowedPersistenceIdentifier(string $persistenceIdentifier): bool + { + try { + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($persistenceIdentifier); + return $adapter->isAllowedPersistenceIdentifier($persistenceIdentifier); + } catch (\Exception) { + return false; + } + } + + /** + * Check if file has valid extension + */ + public function hasValidFileExtension(string $fileName): bool + { + return str_ends_with($fileName, self::FORM_DEFINITION_FILE_EXTENSION); + } + + /** + * Load form definition from storage + */ + private function loadFromStorage(string $persistenceIdentifier, ?ServerRequestInterface $request = null): array + { + try { + $identifier = new FormIdentifier($persistenceIdentifier); + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($persistenceIdentifier); + + return $adapter->read($identifier, $request)->toArray(); + } catch (\Exception $e) { + return [ + 'type' => 'Form', + 'identifier' => $persistenceIdentifier, + 'label' => $e->getMessage(), + 'invalid' => true, + ]; + } + } + + /** + * Check if form with persistence identifier exists + */ + private function exists(string $persistenceIdentifier): bool + { + try { + $identifier = new FormIdentifier($persistenceIdentifier); + $adapter = $this->storageAdapterFactory->getAdapterForIdentifier($persistenceIdentifier); + + return $adapter->exists($identifier); + } catch (\Exception) { + return false; + } + } + + /** + * Check if a form with given identifier already exists in any storage + */ + private function checkForDuplicateIdentifier(string $identifier): bool + { + foreach ($this->storageAdapterFactory->getAllAdapters() as $adapter) { + try { + if ($adapter->existsByFormIdentifier($identifier)) { + return true; + } + } catch (\Exception) { + continue; + } + } + + return false; + } + + protected function sortForms(array $forms, array $formSettings, string $orderField = '', ?string $orderDirection = null): array + { + $persistenceConfiguration = PersistenceManagerConfiguration::fromArray($formSettings['persistenceManager'] ?? []); + if ($orderDirection) { + $ascending = $orderDirection === 'asc'; + } else { + $ascending = $persistenceConfiguration->sortAscending; + } + $sortMultiplier = $ascending ? 1 : -1; + $keys = $orderField ? [$orderField] : $persistenceConfiguration->sortByKeys; + + usort($forms, static function (FormMetadata $a, FormMetadata $b) use ($keys, $sortMultiplier) { + foreach ($keys as $key) { + $aValue = $a->getSortableValue($key); + $bValue = $b->getSortableValue($key); + + if ($aValue === null || $bValue === null) { + continue; + } + + $diff = (is_int($aValue) && is_int($bValue)) + ? $aValue - $bValue + : strcasecmp((string)$aValue, (string)$bValue); + + if ($diff !== 0) { + return $diff * $sortMultiplier; + } + } + return 0; + }); + return $forms; + } + + /** + * Clear cache for specific form + */ + private function clearFormCache(string $persistenceIdentifier): void + { + $cacheKey = 'ext-form-load-' . hash('xxh3', $persistenceIdentifier); + $this->runtimeCache->remove($cacheKey); + } + + public function getAccessibleStorageAdapters(): array + { + $storageAdapters = []; + foreach ($this->storageAdapterFactory->getAllAdapters() as $adapter) { + if ($adapter->isAccessible() === false) { + continue; + } + $storageAdapters[] = [ + 'typeIdentifier' => $adapter->getTypeIdentifier(), + 'label' => $adapter->getLabel(), + 'description' => $adapter->getDescription(), + 'iconIdentifier' => $adapter->getIconIdentifier(), + 'options' => $adapter->getFormManagerOptions(), + ]; + } + return $storageAdapters; + } +} diff --git a/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php b/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php new file mode 100644 index 0000000..68b62a4 --- /dev/null +++ b/Classes/Mvc/Persistence/FormPersistenceManagerInterface.php @@ -0,0 +1,100 @@ + 'Form 01', 'persistenceIdentifier' => 'path1'], [ .... ]] + */ + public function listForms(array $formSettings, SearchCriteria $searchCriteria): array; + + /** + * Check if any form definition is available + */ + public function hasForms(array $formSettings): bool; + + /** + * This takes a form identifier and returns a unique persistence identifier for it. + */ + public function getUniquePersistenceIdentifier(string $storage, string $formIdentifier, ?string $savePath): string; + + public function getUniqueIdentifier(string $identifier): string; + + /** + * Check if a storage location (PID for database, folder path for files) is allowed + * + * @param string $storageLocation The storage location (e.g., "123" for PID, "1:/forms/" for file path) + * @return bool True if the storageLocation is allowed + */ + public function isAllowedStorageLocation(string $storageLocation): bool; + + /** + * Check if a persistence identifier (UID for database, full file path for files) is allowed + * + * @param string $persistenceIdentifier The persistence identifier (e.g., "456" for UID, "1:/forms/contact.form.yaml" for file) + * @return bool True if the persistence identifier is allowed + */ + public function isAllowedPersistenceIdentifier(string $persistenceIdentifier): bool; + + public function hasValidFileExtension(string $fileName): bool; + + public function getAccessibleStorageAdapters(): array; +} diff --git a/Classes/Mvc/ProcessingRule.php b/Classes/Mvc/ProcessingRule.php new file mode 100644 index 0000000..d78d788 --- /dev/null +++ b/Classes/Mvc/ProcessingRule.php @@ -0,0 +1,200 @@ +propertyMappingConfiguration = GeneralUtility::makeInstance(PropertyMappingConfiguration::class); + /** @var ConjunctionValidator $validator */ + $validator = $validatorResolver->createValidator(ConjunctionValidator::class); + $this->validator = $validator; + $this->processingMessages = GeneralUtility::makeInstance(Result::class); + } + + /** + * @internal + */ + public function getPropertyMappingConfiguration(): PropertyMappingConfiguration + { + return $this->propertyMappingConfiguration; + } + + /** + * @internal + */ + public function getDataType(): string + { + return $this->dataType; + } + + /** + * @internal + */ + public function setDataType(string $dataType) + { + $this->dataType = $dataType; + } + + /** + * Returns the child validators of the ConjunctionValidator that is bound to this processing rule + * + * @internal + */ + public function getValidators(): \SplObjectStorage + { + return $this->validator->getValidators(); + } + + /** + * @internal + */ + public function addValidator(ValidatorInterface $validator) + { + $this->validator->addValidator($validator); + } + + /** + * Initializes a new validator container + * + * @internal + */ + public function removeAllValidators(): void + { + $this->filterValidators(fn() => false); + } + + /** + * Filters validators based on a closure + * + * @internal + */ + public function filterValidators(\Closure $filter): void + { + $validatorsToRemove = new \SplObjectStorage(); + $validators = $this->getValidators(); + foreach ($validators as $validator) { + if (!$filter($validator)) { + $validatorsToRemove->offsetSet($validator); + } + } + $validators->removeAll($validatorsToRemove); + } + + /** + * Removes the specified validator. + * + * @param ValidatorInterface $validator The validator to remove + * @throws \TYPO3\CMS\Extbase\Validation\Exception\NoSuchValidatorException + * @internal + */ + public function removeValidator(ValidatorInterface $validator) + { + $this->validator->removeValidator($validator); + } + + /** + * @param mixed $value + * @return mixed + * @internal + */ + public function process($value) + { + if ($this->dataType !== null) { + $value = $this->propertyMapper->convert($value, $this->dataType, $this->propertyMappingConfiguration); + $messages = $this->propertyMapper->getMessages(); + $this->propertyMapper->resetMessages(); + } else { + $messages = GeneralUtility::makeInstance(Result::class); + } + + // PropertyMapper::convert() already records the TypeConverter's Error in + // $messages (via doMapping()) and returns null. If errors are present at + // this point, running validators on a null value would add spurious errors + // that mask the real rejection reason — skip them. + if ($messages->hasErrors()) { + $this->processingMessages->merge($messages); + return $value; + } + + // For multi-value fields (e.g. multi-file uploads) the converted value + // is an ObjectStorage. By default, validators receive the whole collection + // (backwards compatible). Validators implementing ObjectStorageElementValidatorInterface + // (e.g. MimeTypeValidator, FileSizeValidator) are called once per element instead. + if ($value instanceof ObjectStorage) { + foreach ($this->getValidators() as $validator) { + $targets = $validator instanceof ObjectStorageElementValidatorInterface + ? iterator_to_array($value) + : [$value]; + foreach ($targets as $target) { + $messages->merge($validator->validate($target)); + } + } + } else { + $messages->merge($this->validator->validate($value)); + } + + $this->processingMessages->merge($messages); + return $value; + } + + /** + * @internal + */ + public function getProcessingMessages(): Result + { + return $this->processingMessages; + } +} diff --git a/Classes/Mvc/Property/Exception/TypeConverterException.php b/Classes/Mvc/Property/Exception/TypeConverterException.php new file mode 100644 index 0000000..3216be3 --- /dev/null +++ b/Classes/Mvc/Property/Exception/TypeConverterException.php @@ -0,0 +1,43 @@ +render(), $error->getCode()); + $exception->error = $error; + + return $exception; + } + + public function getError(): Error + { + if ($this->error === null) { + return new Error($this->getMessage(), $this->getCode(), [$this->getPrevious()]); + } + + return $this->error; + } +} diff --git a/Classes/Mvc/Property/PropertyMappingConfiguration.php b/Classes/Mvc/Property/PropertyMappingConfiguration.php new file mode 100644 index 0000000..3be206a --- /dev/null +++ b/Classes/Mvc/Property/PropertyMappingConfiguration.php @@ -0,0 +1,143 @@ +formRuntime->getFormDefinition()->getRenderablesRecursively() as $renderable) { + $this->adjustPropertyMappingForFileUploadsAtRuntime($event->formRuntime, $renderable); + } + } + + /** + * Adjusts property mapping configuration for file upload elements at runtime. + * + * At this point, form definition properties (from YAML) are fully available, + * unlike in initializeFormElement() which runs before YAML properties are set. + * + * This sets: + * - CONFIGURATION_UPLOAD_SEED: derived from the form session identifier + * for creating storage sub-folders. + * - CONFIGURATION_ALLOW_REMOVAL: from the element's 'allowRemoval' property + * to enable HMAC-signed file deletion. + * + * It also registers the MimeTypeValidator based on the 'allowedMimeTypes' + * property. This must happen here (and not in FileUpload::initializeFormElement()) + * because the concrete form definition properties are only available at runtime. + */ + protected function adjustPropertyMappingForFileUploadsAtRuntime( + FormRuntime $formRuntime, + RenderableInterface $renderable + ): void { + if (!$renderable instanceof FileUpload + || $formRuntime->getFormSession() === null + || !$formRuntime->canProcessFormSubmission() + ) { + return; + } + $processingRule = $renderable->getRootForm() + ->getProcessingRule($renderable->getIdentifier()); + + if ($renderable->getProperties()['multiple'] ?? false) { + $processingRule->setDataType(ObjectStorage::class); + } + + $this->registerMimeTypeValidator($processingRule, $renderable); + + $propertyMappingConfiguration = $processingRule->getPropertyMappingConfiguration(); + + // Pass all registered validators to the TypeConverter so they can run on the + // PseudoFile *before* the file is written to FAL storage. This prevents invalid + // files (wrong MIME type, oversized, etc.) from ever being persisted. + // All validators are forwarded — not only ObjectStorageElementValidatorInterface + // ones — because that interface only controls per-element fan-out inside + // ProcessingRule::process() for ObjectStorage values; it is unrelated to whether + // a validator is meaningful at the individual-file level. Validators that do not + // handle PseudoFile (e.g. NotEmptyValidator) treat it as a non-null value and + // return valid, which is the correct behaviour at this stage. + $preStorageValidators = iterator_to_array($processingRule->getValidators()); + if ($preStorageValidators !== []) { + $propertyMappingConfiguration->setTypeConverterOption( + UploadedFileReferenceConverter::class, + UploadedFileReferenceConverter::CONFIGURATION_PRE_STORAGE_VALIDATORS, + $preStorageValidators + ); + } + + $propertyMappingConfiguration->setTypeConverterOption( + UploadedFileReferenceConverter::class, + UploadedFileReferenceConverter::CONFIGURATION_UPLOAD_SEED, + $formRuntime->getFormSession()->getIdentifier() + ); + + $propertyMappingConfiguration->setTypeConverterOption( + UploadedFileReferenceConverter::class, + UploadedFileReferenceConverter::CONFIGURATION_ALLOW_REMOVAL, + (bool)($renderable->getProperties()['allowRemoval'] ?? false) + ); + } + + /** + * Registers the MimeTypeValidator for the given file upload element based on + * its 'allowedMimeTypes' property. + * + * The validator is only added once, even if this method is called multiple + * times during a request. + */ + protected function registerMimeTypeValidator( + ProcessingRule $processingRule, + FileUpload $renderable + ): void { + $allowedMimeTypes = []; + if (is_array($renderable->getProperties()['allowedMimeTypes'] ?? null)) { + $allowedMimeTypes = array_filter($renderable->getProperties()['allowedMimeTypes']); + } + if ($allowedMimeTypes === []) { + return; + } + + foreach ($processingRule->getValidators() as $validator) { + if ($validator instanceof MimeTypeValidator) { + return; + } + } + + $mimeTypeValidator = GeneralUtility::makeInstance(ValidatorResolver::class) + ->createValidator(MimeTypeValidator::class, ['allowedMimeTypes' => $allowedMimeTypes]); + $processingRule->addValidator($mimeTypeValidator); + } +} diff --git a/Classes/Mvc/Property/TypeConverter/FormDefinitionArrayConverter.php b/Classes/Mvc/Property/TypeConverter/FormDefinitionArrayConverter.php new file mode 100644 index 0000000..9110789 --- /dev/null +++ b/Classes/Mvc/Property/TypeConverter/FormDefinitionArrayConverter.php @@ -0,0 +1,203 @@ +retrieveSessionToken($formPersistenceIdentifier); + + $prototypeName = $rawFormDefinitionArray['prototypeName'] ?? null; + $identifier = $rawFormDefinitionArray['identifier'] ?? null; + + // A modification of the properties "prototypeName" and "identifier" from the root form element + // through the form editor is always forbidden. + try { + if (!$this->formDefinitionValidationService->isPropertyValueEqualToHistoricalValue([$identifier, 'identifier'], $identifier, $rawFormDefinitionArray['_orig_identifier'] ?? [], $sessionToken)) { + throw new PropertyException('Unauthorized modification of "identifier".', 1528538324); + } + + if (!$this->formDefinitionValidationService->isPropertyValueEqualToHistoricalValue([$identifier, 'prototypeName'], $prototypeName, $rawFormDefinitionArray['_orig_prototypeName'] ?? [], $sessionToken)) { + throw new PropertyException('Unauthorized modification of "prototype name".', 1528538323); + } + } catch (PropertyException $e) { + throw new PropertyException('Unauthorized modification of "prototype name" or "identifier".', 1528538322); + } + + $this->formDefinitionValidationService->validateFormDefinitionProperties($rawFormDefinitionArray, $prototypeName, $sessionToken); + + // @todo move all the transformations to FormDefinitionConversionService + $rawFormDefinitionArray = $this->filterEmptyArrays($rawFormDefinitionArray); + $rawFormDefinitionArray = $this->transformMultiValueElementsForFormFramework($rawFormDefinitionArray); + + // Get RTE property paths for transformation and sanitization + $rtePropertyPaths = $this->getRtePropertyPaths($prototypeName); + + // Transform RTE content using RteHtmlParser before persistence + if ($rtePropertyPaths !== []) { + $rawFormDefinitionArray = $this->formDefinitionConversionService->transformRteContentForPersistence( + $rawFormDefinitionArray, + $rtePropertyPaths + ); + } + + // Sanitize HTML: RTE fields use HtmlSanitizer, all others use strip_tags + $rawFormDefinitionArray = $this->formDefinitionConversionService->sanitizeHtml($rawFormDefinitionArray, $rtePropertyPaths); + $rawFormDefinitionArray = $this->formDefinitionConversionService->removeHmacData($rawFormDefinitionArray); + + // Filter empty arrays again after removeHmacData, as removing _orig_* entries + // can leave previously non-empty arrays (e.g. fluidAdditionalAttributes) empty. + $rawFormDefinitionArray = $this->filterEmptyArrays($rawFormDefinitionArray); + + return GeneralUtility::makeInstance(FormDefinitionArray::class, $rawFormDefinitionArray); + } + + /** + * Some data which is build by the form editor needs a transformation before + * it can be used by the framework. + * Multivalue elements like select elements produce data like: + * + * [ + * _label => 'label' + * _value => 'value' + * ] + * + * This method transforms this into: + * + * [ + * 'value' => 'label' + * ] + * + * @param array $input + */ + protected function transformMultiValueElementsForFormFramework(array $input): array + { + $output = []; + + foreach ($input as $key => $value) { + if (is_int($key) && is_array($value) && isset($value['_label']) && isset($value['_value'])) { + $key = $value['_value']; + $value = $value['_label']; + } + + if (is_array($value)) { + $output[$key] = $this->transformMultiValueElementsForFormFramework($value); + } else { + $output[$key] = $value; + } + } + + return $output; + } + + /** + * Remove keys from an array if the key value is an empty array + * + * @todo ArrayUtility? + */ + protected function filterEmptyArrays(array $array): array + { + foreach ($array as $key => $value) { + if (!is_array($value)) { + continue; + } + if (empty($value)) { + unset($array[$key]); + continue; + } + $array[$key] = $this->filterEmptyArrays($value); + if (empty($array[$key])) { + unset($array[$key]); + } + } + + return $array; + } + + protected function retrieveSessionToken(string $formPersistenceIdentifier): string + { + return $this->formDefinitionConversionService->retrieveSessionToken($formPersistenceIdentifier); + } + + /** + * Get RTE-enabled property paths from the prototype configuration. + * + * @param string|null $prototypeName The prototype name + * @return array Map of element types to their RTE property paths + */ + protected function getRtePropertyPaths(?string $prototypeName): array + { + if ($prototypeName === null) { + return []; + } + + try { + $prototypeConfiguration = $this->configurationService->getPrototypeConfiguration($prototypeName); + return $this->formDefinitionConversionService->extractRtePropertyPaths($prototypeConfiguration); + } catch (\Exception $e) { + // If prototype configuration is not available, return empty array + return []; + } + } +} diff --git a/Classes/Mvc/Property/TypeConverter/PseudoFile.php b/Classes/Mvc/Property/TypeConverter/PseudoFile.php new file mode 100644 index 0000000..89284cd --- /dev/null +++ b/Classes/Mvc/Property/TypeConverter/PseudoFile.php @@ -0,0 +1,106 @@ +nameFileInfo = new \SplFileInfo($uploadInfo['name']); + $this->payloadFilePath = $uploadInfo['tmp_name']; + $this->payloadFileInfo = GeneralUtility::makeInstance(FileInfo::class, $uploadInfo['tmp_name']); + } + + public function getName(): string + { + return $this->nameFileInfo->getBasename(); + } + + public function getNameWithoutExtension(): string + { + // `image...png` + return rtrim( + $this->nameFileInfo->getBasename($this->getExtension()), + '.' + ); + } + + public function getExtension(): string + { + return $this->nameFileInfo->getExtension(); + } + + public function getSize(): ?int + { + // returns `null` in case size is empty (includes `0`) + // @see \TYPO3\CMS\Core\Resource\AbstractFile::getSize() + return $this->payloadFileInfo->getSize() ?: null; + } + + public function getMimeType(): ?string + { + $mimeType = $this->payloadFileInfo->getMimeType(); + return is_string($mimeType) ? $mimeType : null; + } + + public function getContents(): string + { + return file_get_contents($this->payloadFilePath); + } + + public function getSha1(): string + { + return sha1_file($this->payloadFilePath); + } +} diff --git a/Classes/Mvc/Property/TypeConverter/PseudoFileReference.php b/Classes/Mvc/Property/TypeConverter/PseudoFileReference.php new file mode 100644 index 0000000..2371b80 --- /dev/null +++ b/Classes/Mvc/Property/TypeConverter/PseudoFileReference.php @@ -0,0 +1,86 @@ +uid > 0) { + $this->_uid = (int)$this->uid; + return ['_uid']; + } + if ($this->getOriginalResource()->getUid() > 0) { + $this->_uid = $this->getOriginalResource()->getUid(); + return ['_uid']; + } + // in case this is a transient file reference, just expose the associated `sys_file.uid` + // (based on previous comments, this is the most probably case in ext:form) + $this->_uidLocal = $this->getOriginalResource()->getOriginalFile()->getUid(); + return ['_uidLocal']; + } + + public function __wakeup(): void + { + $factory = GeneralUtility::makeInstance(ResourceFactory::class); + if ($this->_uid > 0) { + $this->originalResource = $factory->getFileReferenceObject($this->_uid); + } elseif ($this->_uidLocal > 0) { + $this->originalResource = $factory->createFileReferenceObject([ + 'uid_local' => $this->_uidLocal, + 'uid_foreign' => 0, + 'uid' => 0, + 'crop' => null, + ]); + } else { + throw new \LogicException( + sprintf('Cannot unserialize %s', static::class), + 1613216548 + ); + } + unset($this->_uid, $this->_uidLocal); + } +} diff --git a/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php b/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php new file mode 100644 index 0000000..9d8a679 --- /dev/null +++ b/Classes/Mvc/Property/TypeConverter/UploadedFileReferenceConverter.php @@ -0,0 +1,637 @@ +translationService = $translationService; + } + + /** + * @internal + */ + public function injectResourceFactory(ResourceFactory $resourceFactory): void + { + $this->resourceFactory = $resourceFactory; + } + + /** + * @internal + */ + public function injectHashService(HashService $hashService): void + { + $this->hashService = $hashService; + } + + /** + * @internal + */ + public function injectPersistenceManager(PersistenceManagerInterface $persistenceManager): void + { + $this->persistenceManager = $persistenceManager; + } + + /** + * @internal + */ + public function injectStorageRepository(StorageRepository $storageRepository): void + { + $this->storageRepository = $storageRepository; + } + + /** + * Actually convert from $source to $targetType, taking into account the fully + * built $convertedChildProperties and $configuration. + * + * @param array|UploadedFile|string $source + * @param string $targetType + * @return FileReference|ObjectStorage|Error|null + * @internal + */ + public function convertFrom($source, $targetType, array $convertedChildProperties = [], ?PropertyMappingConfigurationInterface $configuration = null) + { + if ($source === '' || $source === []) { + return null; + } + + if ($source instanceof UploadedFile) { + return $this->convertSingleUpload( + $this->convertUploadedFileToUploadInfoArray($source), + $convertedChildProperties, + $configuration, + ); + } + + $allowRemoval = $configuration?->getConfigurationValue(self::class, self::CONFIGURATION_ALLOW_REMOVAL) ?? false; + + $deleteFileIndices = []; + $filesToDelete = []; + if ($allowRemoval) { + [$deleteFileIndices, $filesToDelete] = $this->extractFileDeletionData($source); + $this->deleteUploadedFiles($filesToDelete); + } + unset($source['__deleteFile']); + + if ($this->isMultiUploadTarget($source, $targetType)) { + return $this->handleMultiUploadSource($source, $deleteFileIndices, $convertedChildProperties, $configuration); + } + + return $this->handleSingleUploadSource($source, $filesToDelete, $allowRemoval, $convertedChildProperties, $configuration); + } + + /** + * Determines whether the source should be treated as a multi-file upload. + * + * Multi-upload is detected when: + * - the target type is ObjectStorage, or + * - the source contains '__submittedFiles' with more than one entry, or + * - the source contains numeric keys holding sub-arrays / UploadedFile objects + * (i.e. no flat 'error' key at the top level). + */ + private function isMultiUploadTarget(array $source, string $targetType): bool + { + if (is_a($targetType, ObjectStorage::class, true)) { + return true; + } + // Fallback heuristic for edge cases where targetType is not ObjectStorage + // but the source structure clearly indicates multi-upload. + if (isset($source['__submittedFiles']) && count($source['__submittedFiles']) > 1) { + return true; + } + return !array_key_exists('error', $source) && !isset($source['submittedFile']) && !isset($source['__submittedFiles']); + } + + /** + * Handles single file upload: standard upload, existing resource pointer only, + * or new upload replacing a previous file. + * + * '__submittedFiles' contains existing resource pointers from hidden inputs. + * 'error' is PHP's native UPLOAD_ERR_* constant from $_FILES. + * + * @param list $filesToDelete + */ + private function handleSingleUploadSource( + array $source, + array $filesToDelete, + bool $allowRemoval, + array $convertedChildProperties, + ?PropertyMappingConfigurationInterface $configuration, + ): FileReference|Error|null { + // Extract the submitted file resource pointer from __submittedFiles + $submittedResourcePointer = null; + if (is_array($source['__submittedFiles'] ?? null)) { + $firstSubmitted = reset($source['__submittedFiles']); + $submittedResourcePointer = $firstSubmitted['submittedFile']['resourcePointer'] ?? null; + } + unset($source['__submittedFiles']); + + // Build a flat source array for convertSingleUpload compatibility + if ($submittedResourcePointer !== null) { + $source['submittedFile']['resourcePointer'] = $submittedResourcePointer; + } + + if ($allowRemoval && $filesToDelete !== []) { + unset($source['submittedFile']['resourcePointer']); + } + + // New upload replaces existing file – clean up the old one + if (isset($source['submittedFile']['resourcePointer'], $source['error']) && $source['error'] === \UPLOAD_ERR_OK + ) { + $this->deletePreviousUpload($source); + unset($source['submittedFile']); + } + + return $this->convertSingleUpload($source, $convertedChildProperties, $configuration); + } + + /** + * @param list $deleteFileIndices + */ + private function handleMultiUploadSource( + array $source, + array $deleteFileIndices, + array $convertedChildProperties, + ?PropertyMappingConfigurationInterface $configuration, + ): ObjectStorage|Error { + $files = new ObjectStorage(); + + // Extract existing file resource pointers from the dedicated sub-key. + // These are stored separately to avoid index collision with new UploadedFile + // objects during array_replace_recursive() in RequestBuilder. + $submittedFiles = []; + if (is_array($source['__submittedFiles'] ?? null)) { + $submittedFiles = $source['__submittedFiles']; + } + unset($source['__submittedFiles']); + + // Process existing files (resource pointers from previous uploads) + $existingFileIndex = 0; + foreach ($submittedFiles as $file) { + if (in_array($existingFileIndex, $deleteFileIndices, true)) { + $existingFileIndex++; + continue; + } + if (is_array($file)) { + $convertedFile = $this->convertSingleUpload( + $file, + $convertedChildProperties, + $configuration, + ); + if ($convertedFile instanceof Error) { + return $convertedFile; + } + if ($convertedFile !== null) { + $files->attach($convertedFile); + } + } + $existingFileIndex++; + } + + // Process new file uploads + foreach ($source as $file) { + if ($file instanceof UploadedFile || is_array($file)) { + $convertedFile = $this->convertSingleUpload( + $file instanceof UploadedFile ? $this->convertUploadedFileToUploadInfoArray($file) : $file, + $convertedChildProperties, + $configuration, + ); + if ($convertedFile instanceof Error) { + return $convertedFile; + } + if ($convertedFile !== null) { + $files->attach($convertedFile); + } + } + } + + return $files; + } + + /** + * Core conversion: upload info array → FileReference, Error, or null. + */ + private function convertSingleUpload( + array $source, + array $convertedChildProperties, + ?PropertyMappingConfigurationInterface $configuration, + ): FileReference|Error|null { + $resourcePublicationSlot = GeneralUtility::makeInstance(ResourcePublicationSlot::class); + + if (!isset($source['error']) || $source['error'] === \UPLOAD_ERR_NO_FILE) { + if (isset($source['submittedFile']['resourcePointer'])) { + try { + $resourcePointer = $this->hashService->validateAndStripHmac( + $source['submittedFile']['resourcePointer'], + HashScope::ResourcePointer->prefix(), + ); + if (str_starts_with($resourcePointer, 'file:')) { + $fileUid = (int)substr($resourcePointer, 5); + $resource = $this->createFileReferenceFromFalFileObject( + $this->resourceFactory->getFileObject($fileUid), + ); + } else { + $resource = $this->createFileReferenceFromFalFileReferenceObject( + $this->resourceFactory->getFileReferenceObject((int)$resourcePointer), + (int)$resourcePointer, + ); + } + $resourcePublicationSlot->add($resource->getOriginalResource()->getOriginalFile()); + return $resource; + } catch (\InvalidArgumentException) { + // No file uploaded and resource pointer is invalid – discard. + } + } + return null; + } + + if ($source['error'] !== \UPLOAD_ERR_OK) { + return GeneralUtility::makeInstance(Error::class, $this->getUploadErrorMessage($source['error']), 1471715915); + } + + if (isset($this->convertedResources[$source['tmp_name']])) { + return $this->convertedResources[$source['tmp_name']]; + } + + if ($configuration === null) { + throw new \InvalidArgumentException('Argument $configuration must not be null', 1589183114); + } + + try { + $resource = $this->importUploadedResource($source, $configuration); + $resourcePublicationSlot->add($resource->getOriginalResource()->getOriginalFile()); + } catch (TypeConverterException $e) { + return $e->getError(); + } catch (\Exception $e) { + return GeneralUtility::makeInstance(Error::class, $e->getMessage(), $e->getCode()); + } + + $this->convertedResources[$source['tmp_name']] = $resource; + return $resource; + } + + /** + * Deletes a previously uploaded file referenced by submittedFile.resourcePointer. + */ + private function deletePreviousUpload(array $source): void + { + if (!isset($source['submittedFile']['resourcePointer'])) { + return; + } + try { + $resourcePointer = $this->hashService->validateAndStripHmac( + $source['submittedFile']['resourcePointer'], + HashScope::ResourcePointer->prefix(), + ); + $fileUid = str_starts_with($resourcePointer, 'file:') + ? (int)substr($resourcePointer, 5) + : null; + if ($fileUid !== null) { + $this->deleteUploadedFiles([$fileUid]); + } + } catch (InvalidHashStringException) { + // Invalid resource pointer – nothing to delete. + } + } + + /** + * Extracts and validates file deletion data from the source array. + * + * @return array{0: list, 1: list} Array containing [deleteFileIndices, filesToDelete] + */ + private function extractFileDeletionData(array $source): array + { + $deleteFileIndices = []; + $filesToDelete = []; + + if (!array_key_exists('__deleteFile', $source) || !is_array($source['__deleteFile'])) { + return [$deleteFileIndices, $filesToDelete]; + } + + foreach ($source['__deleteFile'] as $signedValue) { + try { + $deleteData = $this->hashService->validateAndStripHmac( + $signedValue, + HashScope::DeleteFile->prefix() + ); + $deleteData = json_decode($deleteData, true, 512, JSON_THROW_ON_ERROR); + if (isset($deleteData['fileIndex'])) { + $deleteFileIndices[] = (int)$deleteData['fileIndex']; + } + if (isset($deleteData['fileUid'])) { + $filesToDelete[] = (int)$deleteData['fileUid']; + } + } catch (InvalidHashStringException $e) { + $this->logger?->warning( + 'Invalid file deletion request: HMAC validation failed.', + ['exception' => $e] + ); + } catch (\JsonException $e) { + $this->logger?->warning( + 'Invalid file deletion request: JSON decoding failed.', + ['exception' => $e] + ); + } + } + + return [$deleteFileIndices, $filesToDelete]; + } + + /** + * Deletes uploaded files from the server and cleans up empty upload folders. + * + * @param list $fileUids + */ + private function deleteUploadedFiles(array $fileUids): void + { + foreach ($fileUids as $fileUid) { + try { + $file = $this->resourceFactory->getFileObject($fileUid); + $parentFolder = $file->getParentFolder(); + $file->delete(); + $this->deleteEmptyUploadFolder($parentFolder); + } catch (\Exception $e) { + $this->logger?->warning( + 'Could not delete uploaded file with uid {fileUid}.', + ['fileUid' => $fileUid, 'exception' => $e] + ); + } + } + } + + /** + * Deletes the upload folder if it's empty and was created by the form framework. + */ + private function deleteEmptyUploadFolder(?Folder $folder): void + { + if ($folder === null) { + return; + } + if (!str_starts_with($folder->getName(), 'form_')) { + return; + } + if ($folder->getFileCount() === 0 + && $folder->getStorage()->countFoldersInFolder($folder) === 0 + ) { + $folder->delete(); + } + } + + /** + * Import a resource and respect configuration given for properties + */ + protected function importUploadedResource( + array $uploadInfo, + PropertyMappingConfigurationInterface $configuration + ): PseudoFileReference { + if (!GeneralUtility::makeInstance(FileNameValidator::class)->isValid($uploadInfo['name'])) { + throw new TypeConverterException('Uploading files with PHP file extensions is not allowed!', 1471710357); + } + // `CONFIGURATION_UPLOAD_SEED` is expected to be defined + // if it's not given any random seed is generated, instead of throwing an exception + $seed = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_SEED) + ?: GeneralUtility::makeInstance(Random::class)->generateRandomHexString(40); + $uploadFolderId = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_FOLDER) ?: $this->defaultUploadFolder; + $conflictMode = DuplicationBehavior::tryFrom($configuration->getConfigurationValue(self::class, self::CONFIGURATION_UPLOAD_CONFLICT_MODE)) ?? $this->defaultConflictMode; + $pseudoFile = GeneralUtility::makeInstance(PseudoFile::class, $uploadInfo); + + $preStorageValidators = $configuration->getConfigurationValue(self::class, self::CONFIGURATION_PRE_STORAGE_VALIDATORS) ?? []; + foreach ($preStorageValidators as $validator) { + $validationResult = $validator->validate($pseudoFile); + if ($validationResult->hasErrors()) { + $firstError = current($validationResult->getErrors()); + throw TypeConverterException::fromError($firstError); + } + } + + $uploadFolder = $this->provideUploadFolder($uploadFolderId); + // current folder name, derived from public random seed (`formSession`) + $currentName = 'form_' . $this->hashService->hmac($seed, self::class); + // sub-folder in $uploadFolder with 160 bit of derived entropy (.../form_<40-chars-hash>/actual.file) + $uploadFolder = $this->provideTargetFolder($uploadFolder, $currentName); + // allow skipping the consistency check, since custom validators have already been executed + $this->skipResourceConsistencyCheckForUploads($uploadFolder->getStorage(), $uploadInfo); + /** @var File $uploadedFile */ + $uploadedFile = $uploadFolder->addUploadedFile($uploadInfo, $conflictMode); + + $resourcePointer = isset($uploadInfo['submittedFile']['resourcePointer']) && !str_contains($uploadInfo['submittedFile']['resourcePointer'], 'file:') + ? (int)$this->hashService->validateAndStripHmac($uploadInfo['submittedFile']['resourcePointer'], HashScope::ResourcePointer->prefix()) + : null; + + $fileReferenceModel = $this->createFileReferenceFromFalFileObject($uploadedFile, $resourcePointer); + + return $fileReferenceModel; + } + + protected function createFileReferenceFromFalFileObject( + File $file, + ?int $resourcePointer = null + ): PseudoFileReference { + $fileReference = $this->resourceFactory->createFileReferenceObject( + [ + 'uid_local' => $file->getUid(), + 'uid_foreign' => StringUtility::getUniqueId('NEW_'), + 'uid' => StringUtility::getUniqueId('NEW_'), + 'crop' => null, + ] + ); + return $this->createFileReferenceFromFalFileReferenceObject($fileReference, $resourcePointer); + } + + /** + * In case no $resourcePointer is given a new file reference domain object + * will be returned. Otherwise the file reference is reconstituted from + * storage and will be updated(!) with the provided $falFileReference. + */ + protected function createFileReferenceFromFalFileReferenceObject( + CoreFileReference $falFileReference, + ?int $resourcePointer = null + ): PseudoFileReference { + if ($resourcePointer === null) { + $fileReference = GeneralUtility::makeInstance(PseudoFileReference::class); + } else { + $fileReference = $this->persistenceManager->getObjectByIdentifier($resourcePointer, PseudoFileReference::class, false); + } + + $fileReference->setOriginalResource($falFileReference); + return $fileReference; + } + + /** + * Returns a human-readable message for the given PHP file upload error + * constant. + */ + protected function getUploadErrorMessage(int $errorCode): string + { + $logMessage = match ($errorCode) { + \UPLOAD_ERR_INI_SIZE => 'The uploaded file exceeds the upload_max_filesize directive in php.ini.', + \UPLOAD_ERR_FORM_SIZE => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', + \UPLOAD_ERR_PARTIAL => 'The uploaded file was only partially uploaded.', + \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', + \UPLOAD_ERR_NO_TMP_DIR => 'Missing a temporary folder.', + \UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk.', + \UPLOAD_ERR_EXTENSION => 'File upload stopped by extension.', + default => 'Unknown upload error.', + }; + $this->logger?->error($logMessage); + + $translationKey = match ($errorCode) { + \UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE => 'upload.error.150530345', + \UPLOAD_ERR_PARTIAL => 'upload.error.150530346', + \UPLOAD_ERR_NO_FILE => 'upload.error.150530347', + default => 'upload.error.150530348', + }; + + return $this->translationService->translate( + $translationKey, + null, + 'EXT:form/Resources/Private/Language/locallang.xlf' + ); + } + + /** + * Ensures that upload folder exists, creates it if it does not. + */ + protected function provideUploadFolder(string $uploadFolderIdentifier): Folder + { + try { + return $this->resourceFactory->getFolderObjectFromCombinedIdentifier($uploadFolderIdentifier); + } catch (FolderDoesNotExistException $exception) { + [$storageId, $storagePath] = explode(':', $uploadFolderIdentifier, 2); + $storage = $this->storageRepository->getStorageObject($storageId); + $folderNames = GeneralUtility::trimExplode('/', $storagePath, true); + $uploadFolder = $this->provideTargetFolder($storage->getRootLevelFolder(), ...$folderNames); + $this->provideFolderInitialization($uploadFolder); + return $uploadFolder; + } + } + + /** + * Ensures that particular target folder exists, creates it if it does not. + */ + protected function provideTargetFolder(Folder $parentFolder, string $folderName): Folder + { + return $parentFolder->hasFolder($folderName) + ? $parentFolder->getSubfolder($folderName) + : $parentFolder->createFolder($folderName); + } + + /** + * Creates empty index.html file to avoid directory indexing, + * in case it does not exist yet. + */ + protected function provideFolderInitialization(Folder $parentFolder): void + { + if (!$parentFolder->hasFile('index.html')) { + $parentFolder->createFile('index.html'); + } + } + + protected function convertUploadedFileToUploadInfoArray(UploadedFile $uploadedFile): array + { + return [ + 'name' => $uploadedFile->getClientFilename(), + 'tmp_name' => $uploadedFile->getTemporaryFileName(), + 'size' => $uploadedFile->getSize(), + 'error' => $uploadedFile->getError(), + 'type' => $uploadedFile->getClientMediaType(), + ]; + } +} diff --git a/Classes/Mvc/Validation/CountValidator.php b/Classes/Mvc/Validation/CountValidator.php new file mode 100644 index 0000000..6984cd1 --- /dev/null +++ b/Classes/Mvc/Validation/CountValidator.php @@ -0,0 +1,73 @@ + [0, 'The minimum count to accept', 'integer'], + 'maximum' => [PHP_INT_MAX, 'The maximum count to accept', 'integer'], + ]; + + /** + * The given value is valid if it is an array or \Countable that contains the specified amount of elements. + */ + public function isValid(mixed $value): void + { + if (!is_array($value) && !($value instanceof \Countable)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1475002976', + 'form' + ), + 1475002976 + ); + return; + } + + $minimum = (int)$this->options['minimum']; + $maximum = (int)$this->options['maximum']; + $count = count($value); + if ($count < $minimum || $count > $maximum) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1475002994', + 'form', + [$minimum, $maximum] + ), + 1475002994, + [$this->options['minimum'], $this->options['maximum']] + ); + } + } +} diff --git a/Classes/Mvc/Validation/DateRangeValidator.php b/Classes/Mvc/Validation/DateRangeValidator.php new file mode 100644 index 0000000..0f0c2e9 --- /dev/null +++ b/Classes/Mvc/Validation/DateRangeValidator.php @@ -0,0 +1,165 @@ + ['', 'The minimum date formatted as Y-m-d or a relative date expression (e.g. "today", "-18 years")', 'string'], + 'maximum' => ['', 'The maximum date formatted as Y-m-d or a relative date expression (e.g. "today", "-18 years")', 'string'], + 'format' => ['Y-m-d', 'The format of the minimum and maximum option', 'string'], + ]; + + /** + * @param mixed $value The value that should be validated + */ + public function isValid(mixed $value): void + { + $options = $this->validateOptions(); + if ($options === null) { + return; + } + + if (!($value instanceof \DateTime)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1521293685', + 'form', + [gettype($value)] + ), + 1521293685 + ); + return; + } + + $minimum = $options['minimum']; + $maximum = $options['maximum']; + $format = $options['format']; + $value->modify('midnight'); + + if ($minimum instanceof \DateTime && $value < $minimum) { + $formattedMinimum = $minimum->format($format); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1521293687', + 'form', + [$formattedMinimum] + ), + 1521293687, + [$formattedMinimum] + ); + } + + if ($maximum instanceof \DateTime && $value > $maximum) { + $formattedMaximum = $maximum->format($format); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1521293686', + 'form', + [$formattedMaximum] + ), + 1521293686, + [$formattedMaximum] + ); + } + } + + /** + * Checks if this validator is correctly configured. + * + * Returns the resolved options array on success, or null if a date + * option is misconfigured. In the latter case a generic validation + * error is added for the end user and the technical details are logged. + */ + private function validateOptions(): ?array + { + $options = $this->options; + if (!empty($this->options['minimum'])) { + $minimum = $this->parseDate($this->options['minimum']); + if ($minimum === null) { + $this->logger->error('DateRangeValidator: The option "minimum" ({value}) could not be converted to DateTime. Use format "{format}" or a relative expression (e.g. "today", "-18 years").', [ + 'value' => $this->options['minimum'], + 'format' => $this->options['format'], + ]); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1748345955', + 'form' + ), + 1748345955 + ); + return null; + } + $minimum->modify('midnight'); + $options['minimum'] = $minimum; + } + + if (!empty($this->options['maximum'])) { + $maximum = $this->parseDate($this->options['maximum']); + if ($maximum === null) { + $this->logger->error('DateRangeValidator: The option "maximum" ({value}) could not be converted to DateTime. Use format "{format}" or a relative expression (e.g. "today", "-18 years").', [ + 'value' => $this->options['maximum'], + 'format' => $this->options['format'], + ]); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1748345955', + 'form' + ), + 1748345955 + ); + return null; + } + $maximum->modify('midnight'); + $options['maximum'] = $maximum; + } + return $options; + } + + /** + * Parse a date string as absolute format first, then fall back to relative expressions. + * + * Supports: + * - Absolute dates matching the configured format (e.g. "2025-03-17") + * - Any relative date expression accepted by PHP's DateTime parser + * (e.g. "today", "-18 years", "last sunday", "first day of next month") + */ + private function parseDate(string $value): ?\DateTime + { + $date = \DateTime::createFromFormat($this->options['format'], $value); + if ($date instanceof \DateTime) { + return $date; + } + + return DateRangeValidatorPatterns::parseRelativeDateExpression($value); + } +} diff --git a/Classes/Mvc/Validation/EmptyValidator.php b/Classes/Mvc/Validation/EmptyValidator.php new file mode 100644 index 0000000..89779d9 --- /dev/null +++ b/Classes/Mvc/Validation/EmptyValidator.php @@ -0,0 +1,52 @@ +addError( + $this->translateErrorMessage( + 'validation.error.1476396435', + 'form' + ), + 1476396435 + ); + } + } +} diff --git a/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php b/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php new file mode 100644 index 0000000..0d07f3d --- /dev/null +++ b/Classes/Mvc/Validation/Exception/InvalidValidationOptionsException.php @@ -0,0 +1,22 @@ + ['0B', 'The minimum file size to accept', 'string'], + 'maximum' => [PHP_INT_MAX . 'B', 'The maximum file size to accept', 'string'], + ]; + + /** + * The given value is valid + * + * @param mixed $resource + */ + public function isValid(mixed $resource): void + { + $this->validateOptions(); + if ($resource instanceof FileReference) { + $fileSize = $resource->getOriginalResource()->getSize(); + } elseif ($resource instanceof File) { + $fileSize = $resource->getSize(); + } elseif ($resource instanceof PseudoFile) { + $fileSize = $resource->getSize(); + } else { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1505303626', + 'form' + ), + 1505303626 + ); + return; + } + + $minFileSize = GeneralUtility::getBytesFromSizeMeasurement($this->options['minimum']); + $maxFileSize = GeneralUtility::getBytesFromSizeMeasurement($this->options['maximum']); + + $labels = ' Bytes| Kilobyte| Megabyte| Gigabyte'; + if ($fileSize < $minFileSize) { + $formattedMinFileSize = GeneralUtility::formatSize($minFileSize, $labels); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1505305752', + 'form', + [$formattedMinFileSize] + ), + 1505305752, + [$formattedMinFileSize] + ); + } + if ($fileSize > $maxFileSize) { + $formattedMaxFileSize = GeneralUtility::formatSize($maxFileSize, $labels); + $this->addError( + $this->translateErrorMessage( + 'validation.error.1505305753', + 'form', + [$formattedMaxFileSize] + ), + 1505305753, + [$formattedMaxFileSize] + ); + } + } + + /** + * Checks if this validator is correctly configured + * + * @throws InvalidValidationOptionsException if the configured validation options are incorrect + */ + private function validateOptions(): void + { + if (!preg_match('/^(\d*\.?\d+)(B|K|M|G)$/i', $this->options['minimum'])) { + throw new InvalidValidationOptionsException('The option "minimum" has an invalid format. Valid formats are something like this: "10B|K|M|G".', 1505304205); + } + if (!preg_match('/^(\d*\.?\d+)(B|K|M|G)$/i', $this->options['maximum'])) { + throw new InvalidValidationOptionsException('The option "maximum" has an invalid format. Valid formats are something like this: "10B|K|M|G".', 1505304206); + } + } +} diff --git a/Classes/Mvc/Validation/MimeTypeValidator.php b/Classes/Mvc/Validation/MimeTypeValidator.php new file mode 100644 index 0000000..74c7c52 --- /dev/null +++ b/Classes/Mvc/Validation/MimeTypeValidator.php @@ -0,0 +1,115 @@ + [null, 'Allowed mime types (using */* IANA media types)', 'array', true], + ]; + + /** + * The given $value is valid if it is a FileReference of the + * configured type (one of the IANA media types) + * + * Note: a value of NULL or empty string ('') is considered valid + * + * @param mixed $resource The resource that should be validated + */ + public function isValid(mixed $resource): void + { + $this->validateOptions(); + + if ($resource instanceof FileReference) { + $mimeType = $resource->getOriginalResource()->getMimeType(); + $fileExtension = $resource->getOriginalResource()->getExtension(); + } elseif ($resource instanceof File) { + $mimeType = $resource->getMimeType(); + $fileExtension = $resource->getExtension(); + } elseif ($resource instanceof PseudoFile) { + $mimeType = $resource->getMimeType(); + $fileExtension = $resource->getExtension(); + } else { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1471708997', + 'form' + ), + 1471708997 + ); + return; + } + + $allowedMimeTypes = $this->options['allowedMimeTypes']; + if (!in_array($mimeType, $allowedMimeTypes, true)) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1471708998', + 'form', + [$mimeType] + ), + 1471708998, + [$mimeType] + ); + } else { + // The mime-type which was detected by FAL matches, but the file name does not match. + // Example: myfile.txt is actually a PDF file (defined by mime-type), but .txt is not associated + // for application/pdf, so this is not valid. The file extension of the uploaded file must match + // the mime-type for this file. + $assumedMimesTypeOfFileExtension = (new MimeTypeDetector())->getMimeTypesForFileExtension($fileExtension); + if (empty(array_intersect($allowedMimeTypes, $assumedMimesTypeOfFileExtension))) { + $this->addError( + $this->translateErrorMessage( + 'validation.error.1613126216', + 'form', + [$fileExtension] + ), + 1613126216, + [$fileExtension] + ); + } + } + } + + /** + * Checks if this validator is correctly configured + * + * @throws InvalidValidationOptionsException if the configured validation options are incorrect + */ + private function validateOptions(): void + { + if (!is_array($this->options['allowedMimeTypes'] ?? null) || $this->options['allowedMimeTypes'] === []) { + throw new InvalidValidationOptionsException('The option "allowedMimeTypes" must be an array with at least one item.', 1471713296); + } + } +} diff --git a/Classes/Mvc/Validation/ObjectStorageElementValidatorInterface.php b/Classes/Mvc/Validation/ObjectStorageElementValidatorInterface.php new file mode 100644 index 0000000..1a7e9d4 --- /dev/null +++ b/Classes/Mvc/Validation/ObjectStorageElementValidatorInterface.php @@ -0,0 +1,32 @@ +standardContentPreviewRenderer->renderPageModulePreviewHeader($item); + } + + public function renderPageModulePreviewContent(GridColumnItem $item): string + { + $record = $item->getRecord(); + $request = $item->getContext()->getCurrentRequest(); + $persistenceIdentifier = null; + if ($record->has('pi_flexform')) { + $flexFormData = $record->get('pi_flexform'); + if ($flexFormData instanceof FlexFormFieldValues) { + if ($flexFormData->has('sDEF/settings.persistenceIdentifier')) { + $persistenceIdentifier = $flexFormData->get('sDEF/settings.persistenceIdentifier'); + } else { + $this->logger->warning( + 'Field "pi_flexform" for record-uid "{uid}" does not contain a persistence identifier.', + ['uid' => $record->getUid()] + ); + } + } else { + $this->logger->warning( + 'Type "{type}" of field "pi_flexform" for record-uid "{uid}" is not valid.', + ['type' => get_debug_type($flexFormData), 'uid' => $record->getUid()] + ); + } + } + $languageService = $this->getLanguageService(); + if (!empty($persistenceIdentifier)) { + try { + try { + $formDefinition = $this->formPersistenceManager->load($persistenceIdentifier); + $formLabel = $formDefinition['label']; + } catch (ParseErrorException $e) { + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.invalidPersistenceIdentifier'), + $persistenceIdentifier + ); + } catch (PersistenceManagerException $e) { + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.inaccessiblePersistenceIdentifier'), + $persistenceIdentifier + ); + } catch (Exception $e) { + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.notExistingdPersistenceIdentifier'), + $persistenceIdentifier + ); + } + } catch (NoSuchFileException $e) { + $this->addInvalidFrameworkConfigurationFlashMessage($persistenceIdentifier, $e); + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.notExistingdPersistenceIdentifier'), + $persistenceIdentifier + ); + } catch (ParseErrorException $e) { + $this->addInvalidFrameworkConfigurationFlashMessage($persistenceIdentifier, $e); + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.invalidFrameworkConfiguration'), + $persistenceIdentifier + ); + } catch (\Exception $e) { + // Top level catch - FAL throws top level exceptions on missing files, eg. in getFileInfoByIdentifier() of LocalDriver + $this->addInvalidFrameworkConfigurationFlashMessage($persistenceIdentifier, $e); + $formLabel = sprintf( + $languageService->sL('form.database:tt_content.preview.invalidFrameworkConfiguration.text'), + $persistenceIdentifier, + $e->getMessage() + ); + } + } else { + $formLabel = $languageService->sL('form.database:tt_content.preview.noPersistenceIdentifier'); + } + $itemContent = '' . htmlspecialchars($item->getContext()->getContentTypeLabels()['form_formframework']) . '
'; + return $this->fieldProcessor->linkToEditForm($itemContent . htmlspecialchars($formLabel), $record, $request); + } + + public function renderPageModulePreviewFooter(GridColumnItem $item): string + { + return $this->standardContentPreviewRenderer->renderPageModulePreviewFooter($item); + } + + public function wrapPageModulePreview(string $previewHeader, string $previewContent, GridColumnItem $item): string + { + return $this->standardContentPreviewRenderer->wrapPageModulePreview($previewHeader, $previewContent, $item); + } + + private function addInvalidFrameworkConfigurationFlashMessage(string $persistenceIdentifier, \Exception $e): void + { + $languageService = $this->getLanguageService(); + $this->flashMessageService + ->getMessageQueueByIdentifier('core.template.flashMessages') + ->enqueue( + new FlashMessage( + sprintf( + $languageService->sL('form.database:tt_content.preview.invalidFrameworkConfiguration.text'), + $persistenceIdentifier, + $e->getMessage() + ), + $languageService->sL('form.database:tt_content.preview.invalidFrameworkConfiguration.title'), + ContextualFeedbackSeverity::ERROR, + true + ) + ); + } + + private function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Security/HashScope.php b/Classes/Security/HashScope.php new file mode 100644 index 0000000..adc52a8 --- /dev/null +++ b/Classes/Security/HashScope.php @@ -0,0 +1,38 @@ +value; + } +} diff --git a/Classes/Service/CleanupFormUploadsService.php b/Classes/Service/CleanupFormUploadsService.php new file mode 100644 index 0000000..a7d3289 --- /dev/null +++ b/Classes/Service/CleanupFormUploadsService.php @@ -0,0 +1,162 @@ +` inside the configured upload folder (default: + * `1:/user_upload/`). Over time, these folders accumulate — both from + * completed and incomplete form submissions. + * + * Since uploaded files are not moved upon form submission, there is no + * way to distinguish between folders from completed and abandoned + * submissions. This service identifies form upload folders based on + * their age (modification time) and provides methods to list and delete them. + * + * @internal + */ +readonly class CleanupFormUploadsService +{ + /** + * Regex matching the folder naming convention used by + * UploadedFileReferenceConverter::importUploadedResource(): + * `form_` followed by exactly 40 hex characters (HMAC output). + */ + private const string FORM_UPLOAD_FOLDER_PATTERN = '/^form_[a-f0-9]{40}$/'; + + public function __construct( + private ResourceFactory $resourceFactory, + private LoggerInterface $logger, + ) {} + + /** + * Finds expired form upload folders in the given upload folders. + * + * A folder is considered expired when: + * 1. Its name matches the `form_<40-hex-chars>` pattern + * 2. Its modification time is older than the given maximum age + * + * @param int $maximumAge Maximum age in seconds. Folders older than this are considered expired. + * @param list $uploadFolderIdentifiers List of combined folder identifiers to scan + * (e.g. ['1:/user_upload/', '2:/custom_uploads/']). + * @return list List of expired form upload folders + */ + public function getExpiredFolders(int $maximumAge, array $uploadFolderIdentifiers): array + { + $cutoffTimestamp = time() - $maximumAge; + $expiredFolders = []; + + foreach ($uploadFolderIdentifiers as $folderIdentifier) { + $expiredFolders = [ + ...$expiredFolders, + ...$this->findExpiredFoldersInParent($folderIdentifier, $cutoffTimestamp), + ]; + } + + return $expiredFolders; + } + + /** + * Deletes the given folders and returns a result summary. + * + * @param list $folders Folders to delete + * @return array{deleted: int, failed: int, errors: list} + */ + public function deleteFolders(array $folders): array + { + $deleted = 0; + $failed = 0; + $errors = []; + + foreach ($folders as $folder) { + try { + $folder->delete(true); + $deleted++; + } catch (\Exception $e) { + $failed++; + $errors[] = [ + 'folder' => $folder->getCombinedIdentifier(), + 'message' => $e->getMessage(), + ]; + $this->logger->error( + 'Failed to delete form upload folder "{folder}": {message}', + ['folder' => $folder->getCombinedIdentifier(), 'message' => $e->getMessage()] + ); + } + } + + return [ + 'deleted' => $deleted, + 'failed' => $failed, + 'errors' => $errors, + ]; + } + + /** + * Find expired form upload folders in a specific parent folder. + * + * @return list + */ + private function findExpiredFoldersInParent(string $folderIdentifier, int $cutoffTimestamp): array + { + $expiredFolders = []; + + try { + $parentFolder = $this->resourceFactory->getFolderObjectFromCombinedIdentifier($folderIdentifier); + } catch (FolderDoesNotExistException|InsufficientFolderAccessPermissionsException|\InvalidArgumentException $e) { + $this->logger->warning( + 'Could not access upload folder "{folder}": {message}', + ['folder' => $folderIdentifier, 'message' => $e->getMessage()] + ); + return $expiredFolders; + } + + foreach ($parentFolder->getSubfolders() as $subFolder) { + if ($this->isExpiredFormUploadFolder($subFolder, $cutoffTimestamp)) { + $expiredFolders[] = $subFolder; + } + } + + return $expiredFolders; + } + + /** + * Determines whether a folder is an expired form upload folder. + * + * A folder is considered an expired form upload folder when: + * 1. Its name matches the exact `form_<40-hex-chars>` pattern + * (as generated by UploadedFileReferenceConverter::importUploadedResource()) + * 2. Its modification time is older than the cutoff timestamp + */ + private function isExpiredFormUploadFolder(Folder $folder, int $cutoffTimestamp): bool + { + if (preg_match(self::FORM_UPLOAD_FOLDER_PATTERN, $folder->getName()) !== 1) { + return false; + } + + return $folder->getModificationTime() < $cutoffTimestamp; + } +} diff --git a/Classes/Service/DatabaseService.php b/Classes/Service/DatabaseService.php new file mode 100644 index 0000000..800dc14 --- /dev/null +++ b/Classes/Service/DatabaseService.php @@ -0,0 +1,219 @@ + interpreted as a sys_file reference UID to a FAL-stored YAML file (user-generated content) + * - EXT:... -> interpreted as a NON-FAL extension-based file + * - any string -> interpreted as FAL-based filename + * + * Note that we explicitly do NOT check for file existence here, + * because we want to be able to reveal sys_refindex entries to files + * that have been deleted meanwhile! + * + * @internal + */ + public function getReferencesByPersistenceIdentifier(string $persistenceIdentifier): array + { + if (empty($persistenceIdentifier)) { + throw new \InvalidArgumentException('$persistenceIdentifier must not be empty.', 1472238493); + } + + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); + $constraints = [$queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier'))]; + + // Indicator whether the string-based lookup in sys_refindex shall be performed (true; non FAL-based) or not (false; FAL-based) + $useStringReference = false; + + // Check what $persistenceIdentifier contains. + if (PathUtility::isExtensionPath($persistenceIdentifier)) { + // Uses "EXT:" notation, so it cannot be a FAL identifier. + // We pass the whole "EXT:..." lookup through to the sys_refindex query + // due to its constraint on softref_key=formPersistenceIdentifier, + // we expect no false entries even with "weird" string notations. If sys_refindex + // has it, we yield it. + $useStringReference = true; + } elseif (MathUtility::canBeInterpretedAsInteger($persistenceIdentifier)) { + $constraints[] = $queryBuilder->expr()->or( + $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier)), + $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($persistenceIdentifier, Connection::PARAM_INT)) + ); + } else { + // Anything else would be either a notation like "/fileadmin/something.form.yaml" + // or a numeric identifier for a sys_file. + try { + // We use this "bulk method" because this is the best-bet from resourceFactory + // to resolve both an integer-ish input value or a FAL value. There is no + // substitute for an "only get a file, not a directory" lookup. + $file = $this->resourceFactory->retrieveFileOrFolderObject($persistenceIdentifier); + + if ($file === null) { + // The associated identifier could (no longer) be retrieved via FAL. + // However, we do want to see existing entries to such stale entries to + // be able to reveal bad references, either by its ref_string or ref_uid + $useStringReference = true; + } elseif ($file instanceof File) { + // We succeeded in retrieving the FAL file object. + $constraints[] = $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($file->getUid(), Connection::PARAM_INT)); + } else { + // We might have retrieved a "Folder" object. Fall back to passthrough + // with the intent, to retrieve all possible sys_refindex entries. + // If that fails, it's ok to return an empty array. + $useStringReference = true; + } + } catch (ResourceDoesNotExistException) { + // This exception gets triggered when $persistenceIdentifier is not something + // that could be resolved by the bulk-method. + // As above, we want to retrieve all the possible sys_refindex entries, + // so we fall back again to "ref_string". + // This should happen when $persistenceIdentifier is set to a string like '/fileadmin/somefile.form.yaml', + // and a FAL storage could be retrieved, but not the actual file. + $useStringReference = true; + } + } + + if ($useStringReference) { + $constraints[] = $queryBuilder->expr()->eq('ref_string', $queryBuilder->createNamedParameter($persistenceIdentifier)); + } + + return $queryBuilder + ->select('*') + ->from('sys_refindex') + ->where(...$constraints) + ->executeQuery() + ->fetchAllAssociative(); + } + + /** + * Returns an array with all form definition persistenceIdentifiers + * as keys and their reference counts as values. + * + * @internal + */ + public function getAllReferencesForPersistenceIdentifier(): array + { + $items = []; + foreach ($this->getAllReferences('ref_string') as $item) { + $items[$item['identifier']] = $item['items']; + } + return $items; + } + + /** + * Returns an array with all form definition file uids as keys + * and their reference counts as values. + * + * @internal + */ + public function getAllReferencesForFileUid(): array + { + $items = []; + foreach ($this->getAllReferences('ref_uid') as $item) { + $items[$item['identifier']] = $item['items']; + } + return $items; + } + + /** + * Returns an array with all database-stored form definition UIDs as keys + * and their reference counts as values. + * + * These are tracked in sys_refindex via ref_table='form_definition' and ref_uid=. + * + * @return array persistenceIdentifier (UID as string) => reference count + * @internal + */ + public function getAllReferencesForFormDefinitionUid(): array + { + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); + + $rows = $queryBuilder + ->select('ref_uid AS identifier') + ->addSelectLiteral('COUNT(' . $queryBuilder->quoteIdentifier('ref_uid') . ') AS ' . $queryBuilder->quoteIdentifier('items')) + ->from('sys_refindex') + ->where( + $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier')), + $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter(FormDefinitionRepository::TABLE_NAME)), + $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)) + ) + ->groupBy('ref_uid') + ->executeQuery() + ->fetchAllAssociative(); + + $items = []; + foreach ($rows as $row) { + $items[(string)$row['identifier']] = (int)$row['items']; + } + return $items; + } + + protected function getAllReferences(string $column): array + { + if ($column !== 'ref_string' && $column !== 'ref_uid') { + throw new \InvalidArgumentException('$column must be "ref_string" or "ref_uid".', 1535406600); + } + + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('sys_refindex'); + + $constraints = [ + $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('formPersistenceIdentifier')), + ]; + + if ($column === 'ref_string') { + $constraints[] = $queryBuilder->expr()->neq('ref_string', $queryBuilder->createNamedParameter('')); + } else { + $constraints[] = $queryBuilder->expr()->gt('ref_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)); + } + + return $queryBuilder + ->select($column . ' AS identifier') + ->addSelectLiteral('COUNT(' . $queryBuilder->quoteIdentifier($column) . ') AS ' . $queryBuilder->quoteIdentifier('items')) + ->from('sys_refindex') + ->where(...$constraints) + ->groupBy($column) + ->executeQuery() + ->fetchAllAssociative(); + } +} diff --git a/Classes/Service/FormEditorEnrichmentService.php b/Classes/Service/FormEditorEnrichmentService.php new file mode 100644 index 0000000..085e2a3 --- /dev/null +++ b/Classes/Service/FormEditorEnrichmentService.php @@ -0,0 +1,137 @@ +enrichDefinitionWithRichTextOptions($definition); + } + } + + return $formEditorDefinitions; + } + + /** + * Enrich a single definition with RTE options for its editors and property collections. + */ + protected function enrichDefinitionWithRichTextOptions(array &$definition): void + { + if (is_array($definition['editors'] ?? null)) { + $this->enrichEditorsWithRichTextOptions($definition['editors']); + } + + if (is_array($definition['propertyCollections'] ?? null)) { + $this->enrichPropertyCollectionsWithRichTextOptions($definition['propertyCollections']); + } + } + + /** + * Enrich property collections (e.g., finishers, validators) with RTE options. + * + * Property collections have an additional numeric level in their structure: + * propertyCollections -> collectionName (e.g., 'finishers') -> numeric index -> editors + */ + protected function enrichPropertyCollectionsWithRichTextOptions(array &$propertyCollections): void + { + foreach ($propertyCollections as &$collectionItems) { + if (!is_array($collectionItems)) { + continue; + } + + foreach ($collectionItems as &$collectionItem) { + if (is_array($collectionItem['editors'] ?? null)) { + $this->enrichEditorsWithRichTextOptions($collectionItem['editors']); + } + } + } + } + + /** + * Enrich editors array with RTE options if enableRichtext is set. + * + * Iterates through all editors and adds RTE configuration options + * to textarea editors that have rich text enabled. + */ + protected function enrichEditorsWithRichTextOptions(array &$editors): void + { + foreach ($editors as &$editor) { + if ($this->shouldEnrichEditorWithRichText($editor)) { + $editor['rteOptions'] = $this->resolveRichTextOptions($editor); + } + } + } + + /** + * Check if an editor should be enriched with RTE options. + * + * An editor qualifies for RTE enrichment if it is a textarea editor + * and has the enableRichtext flag set to true. + */ + protected function shouldEnrichEditorWithRichText(array $editor): bool + { + return ($editor['templateName'] ?? '') === 'Inspector-TextareaEditor' + && ($editor['enableRichtext'] ?? false) === true; + } + + /** + * Resolve CKEditor configuration options for the given editor. + * + * Retrieves the RTE preset configuration and resolves it into + * a complete CKEditor configuration that can be used in the form editor. + */ + protected function resolveRichTextOptions(array $editor): array + { + $presetName = $editor['richtextConfiguration'] ?? 'form-label'; + return $this->richTextConfigurationService->resolveCkEditorConfiguration($presetName); + } +} diff --git a/Classes/Service/FormTransferResult.php b/Classes/Service/FormTransferResult.php new file mode 100644 index 0000000..d4d551d --- /dev/null +++ b/Classes/Service/FormTransferResult.php @@ -0,0 +1,40 @@ +deletionError === null; + } +} diff --git a/Classes/Service/FormTransferService.php b/Classes/Service/FormTransferService.php new file mode 100644 index 0000000..502e6b6 --- /dev/null +++ b/Classes/Service/FormTransferService.php @@ -0,0 +1,330 @@ + + */ + public function listSourceForms(string $sourceType, ?string $formIdentifier = null): array + { + $sourceAdapter = $this->storageAdapterFactory->getAdapterByType($sourceType); + $forms = $sourceAdapter->findAll(new SearchCriteria()); + + if ($formIdentifier !== null) { + $forms = array_values(array_filter( + $forms, + static fn(FormMetadata $form) => $form->identifier === $formIdentifier, + )); + } + + return $forms; + } + + /** + * Read a form definition from a source storage + */ + public function readForm(string $sourceType, string $persistenceIdentifier): FormData + { + return $this->storageAdapterFactory->getAdapterByType($sourceType)->read(FormIdentifier::fromString($persistenceIdentifier)); + } + + /** + * Delete a form from a storage + */ + public function deleteForm(string $storageType, string $persistenceIdentifier): void + { + $adapter = $this->storageAdapterFactory->getAdapterByType($storageType); + $adapter->delete(FormIdentifier::fromString($persistenceIdentifier)); + } + + /** + * Transfer a single form from source to target storage + * + * @return FormTransferResult + */ + public function transferForm( + FormMetadata $sourceForm, + string $sourceType, + string $targetType, + string $targetLocation, + bool $deleteSource = false, + ): FormTransferResult { + $sourceAdapter = $this->storageAdapterFactory->getAdapterByType($sourceType); + $targetAdapter = $this->storageAdapterFactory->getAdapterByType($targetType); + + // Read from source + $sourcePersistenceIdentifier = $sourceForm->persistenceIdentifier ?? $sourceForm->identifier; + $formData = $sourceAdapter->read(FormIdentifier::fromString($sourcePersistenceIdentifier)); + + // Ensure unique identifier in target. + // For a move operation the source form will be deleted afterwards, so it must not be + // counted as a duplicate. Therefore only the target adapter is checked for conflicts. + // For a copy operation all adapters are checked to avoid the same logical identifier + // existing in multiple storages simultaneously. + if ($deleteSource) { + $uniqueIdentifier = $this->getUniqueIdentifierInAdapter($targetAdapter, $formData->identifier); + } else { + $uniqueIdentifier = $this->formPersistenceManager->getUniqueIdentifier($formData->identifier); + } + + // Build FormData with potentially updated identifier + $targetFormData = $uniqueIdentifier !== $formData->identifier + ? FormData::fromArray(array_merge($formData->toArray(), ['identifier' => $uniqueIdentifier])) + : $formData; + + // Get unique persistence identifier in target storage + $targetPersistenceIdentifier = $targetAdapter->getUniquePersistenceIdentifier( + $uniqueIdentifier, + $targetLocation, + ); + + // Write to target + $context = $this->buildStorageContext($targetLocation); + $savedIdentifier = $targetAdapter->write( + FormIdentifier::fromString($targetPersistenceIdentifier), + $targetFormData, + $context, + ); + + // Optionally delete from source + $sourceDeleted = false; + $deletionError = null; + if ($deleteSource) { + try { + $sourceAdapter->delete(FormIdentifier::fromString($sourcePersistenceIdentifier)); + $sourceDeleted = true; + } catch (\Exception $e) { + $deletionError = $e->getMessage(); + } + } + + return new FormTransferResult( + sourceIdentifier: $sourcePersistenceIdentifier, + targetIdentifier: $savedIdentifier->identifier, + formIdentifier: $uniqueIdentifier, + formName: $sourceForm->name, + sourceDeleted: $sourceDeleted, + deletionError: $deletionError, + ); + } + + /** + * Get all registered storage type identifiers + * + * @return list + */ + public function getAvailableStorageTypes(): array + { + return $this->storageAdapterFactory->getRegisteredTypeIdentifiers(); + } + + /** + * Check if a storage type exists + */ + public function hasStorageType(string $typeIdentifier): bool + { + return $this->storageAdapterFactory->hasAdapterType($typeIdentifier); + } + + /** + * Get adapter for a storage type (for validation purposes) + */ + public function getAdapter(string $typeIdentifier): StorageAdapterInterface + { + return $this->storageAdapterFactory->getAdapterByType($typeIdentifier); + } + + /** + * Get a unique form identifier by checking only the given storage adapter for conflicts. + * + * Used for move operations: since the source form is deleted after transfer, only the + * target storage needs to be free of the identifier — not all storages globally. + * + * @throws \RuntimeException if no unique identifier can be found + */ + private function getUniqueIdentifierInAdapter(StorageAdapterInterface $adapter, string $identifier): string + { + $originalIdentifier = $identifier; + + if (!$adapter->existsByFormIdentifier($identifier)) { + return $identifier; + } + + for ($attempts = 1; $attempts < 100; $attempts++) { + $identifier = sprintf('%s_%d', $originalIdentifier, $attempts); + if (!$adapter->existsByFormIdentifier($identifier)) { + return $identifier; + } + } + + $identifier = $originalIdentifier . '_' . time(); + if (!$adapter->existsByFormIdentifier($identifier)) { + return $identifier; + } + + throw new \RuntimeException( + sprintf('Could not find a unique identifier for form identifier "%s" after %d attempts', $originalIdentifier, $attempts), + 1742477400 + ); + } + + private function buildStorageContext(string $targetLocation): ?StorageContext + { + if (ctype_digit($targetLocation)) { + return StorageContext::create((int)$targetLocation); + } + return null; + } + + /** + * Update tt_content FlexForm references from old persistence identifiers + * to new ones. + * + * Uses DOM/XPath parsing to precisely target only the + * `settings.persistenceIdentifier` field in FlexForm XML, avoiding + * false replacements in other fields. + * + * @param array $migrationMap Old persistenceIdentifier => new persistenceIdentifier + * @return int Number of updated content element references + */ + public function updateContentElementReferences(array $migrationMap): int + { + $updatedCount = 0; + $connection = $this->connectionPool->getConnectionForTable('tt_content'); + + $queryBuilder = $this->connectionPool->getQueryBuilderForTable('tt_content'); + $queryBuilder->getRestrictions()->removeAll()->add( + GeneralUtility::makeInstance(DeletedRestriction::class) + ); + + $rows = $queryBuilder + ->select('uid', 'pi_flexform') + ->from('tt_content') + ->where( + $queryBuilder->expr()->eq( + 'CType', + $queryBuilder->createNamedParameter('form_formframework') + ), + $queryBuilder->expr()->isNotNull('pi_flexform'), + $queryBuilder->expr()->neq( + 'pi_flexform', + $queryBuilder->createNamedParameter('') + ) + ) + ->executeQuery() + ->fetchAllAssociative(); + + foreach ($rows as $row) { + $flexForm = $row['pi_flexform']; + $newValue = $this->replacePersistenceIdentifierInFlexForm($flexForm, $migrationMap); + + if ($newValue !== null && $newValue !== $flexForm) { + $connection->update( + 'tt_content', + ['pi_flexform' => $newValue], + ['uid' => (int)$row['uid']] + ); + $updatedCount++; + } + } + + return $updatedCount; + } + + /** + * Replace the persistenceIdentifier value in FlexForm XML using DOM parsing. + * + * Specifically targets only the + * element to avoid replacing values in other FlexForm fields. + * + * @param string $flexFormXml The raw FlexForm XML string + * @param array $migrationMap Old persistenceIdentifier => new persistenceIdentifier + * @return string|null The modified XML string, or null if parsing failed or no changes were made + */ + private function replacePersistenceIdentifierInFlexForm(string $flexFormXml, array $migrationMap): ?string + { + $document = new \DOMDocument(); + $previousErrorHandling = libxml_use_internal_errors(true); + + if (!$document->loadXML($flexFormXml)) { + libxml_clear_errors(); + libxml_use_internal_errors($previousErrorHandling); + $this->logger->warning('Could not parse FlexForm XML.'); + return null; + } + + libxml_clear_errors(); + libxml_use_internal_errors($previousErrorHandling); + + $xpath = new \DOMXPath($document); + $nodes = $xpath->query('//field[@index="settings.persistenceIdentifier"]/value[@index="vDEF"]'); + + if ($nodes === false || $nodes->length === 0) { + return null; + } + + $modified = false; + foreach ($nodes as $node) { + $currentValue = $node->nodeValue; + if (isset($migrationMap[$currentValue])) { + $node->nodeValue = (string)$migrationMap[$currentValue]; + $modified = true; + } + } + + if (!$modified) { + return null; + } + + return $document->saveXML(); + } +} diff --git a/Classes/Service/RichTextConfigurationService.php b/Classes/Service/RichTextConfigurationService.php new file mode 100644 index 0000000..8777e26 --- /dev/null +++ b/Classes/Service/RichTextConfigurationService.php @@ -0,0 +1,327 @@ +loadRichtextConfiguration($presetName); + return $this->prepareConfigurationForEditor($richtextConfiguration); + } + + /** + * Resolves the processing configuration (proc.) for HTML transformations. + * + * This method loads the RTE preset and returns the processing configuration + * that can be used with RteHtmlParser for HTML transformations. + * + * Note: Unlike resolveCkEditorConfiguration(), this method does NOT check for rte_ckeditor + * because RteHtmlParser is part of the Core and works independently of the editor. + * + * @param string $presetName Name of the RTE preset (e.g., 'form-label', 'form-content') + * @return array The processing configuration array + */ + public function resolveProcessingConfiguration(string $presetName = 'form-label'): array + { + + $richtextConfiguration = $this->loadRichtextConfiguration($presetName); + return $richtextConfiguration['proc.'] ?? []; + } + + /** + * Transforms HTML content from RTE format for database persistence. + * + * @param string $htmlContent The HTML content from the RTE editor + * @param string $presetName Name of the RTE preset to use for transformation rules + * @return string The transformed HTML ready for database storage + */ + public function transformTextForPersistence(string $htmlContent, string $presetName = 'form-label'): string + { + $processingConfiguration = $this->resolveProcessingConfiguration($presetName); + return $this->rteHtmlParser->transformTextForPersistence($htmlContent, $processingConfiguration); + } + + /** + * Transforms HTML content from database format for RTE display. + * + * @param string $htmlContent The HTML content from the database + * @param string $presetName Name of the RTE preset to use for transformation rules + * @return string The transformed HTML ready for the RTE editor + */ + public function transformTextForRichTextEditor(string $htmlContent, string $presetName = 'form-label'): string + { + $processingConfiguration = $this->resolveProcessingConfiguration($presetName); + + return $this->rteHtmlParser->transformTextForRichTextEditor($htmlContent, $processingConfiguration); + } + + /** + * Loads the full RTE configuration from the preset. + * + * @param string $presetName Name of the RTE preset + * @return array The full richtext configuration + */ + private function loadRichtextConfiguration(string $presetName): array + { + // Load RTE configuration from TYPO3's global preset system + // We use dummy values since we're in the form editor context without a specific record + return $this->richtext->getConfiguration( + 'tx_form_dummy', + 'dummy_field', + 0, + '', + ['richtextConfiguration' => $presetName] + ); + } + + /** + * Prepares the loaded RTE configuration for the CKEditor. + * + * @param array $richtextConfiguration The raw richtext configuration from preset + * @return array The prepared configuration for CKEditor + */ + private function prepareConfigurationForEditor(array $richtextConfiguration): array + { + $configuration = [ + 'customConfig' => '', + 'label' => '', + ]; + + if (is_array($richtextConfiguration['editor']['config'] ?? null)) { + $configuration = array_replace_recursive($configuration, $richtextConfiguration['editor']['config']); + } + + $this->processExternalPlugins($richtextConfiguration, $configuration); + + $this->configureLanguage($configuration); + + $configuration = $this->replaceLanguageFileReferences($configuration); + $configuration = $this->replaceAbsolutePathsToRelativeResourcesPath($configuration); + + if (!isset($configuration['debug'])) { + $configuration['debug'] = ($GLOBALS['TYPO3_CONF_VARS']['BE']['debug'] ?? false) + && Environment::getContext()->isDevelopment(); + } + + return $configuration; + } + + /** + * Processes external plugins configuration. + * + * External plugins may require additional configuration like route URLs for the link browser. + * This method handles the transformation of route names to actual URLs. + * + * Similar to RichTextElement::getExtraPlugins() and resolveCkEditorConfiguration(). + * + * @param array $richtextConfiguration The full richtext configuration + * @param array $configuration The configuration array to modify (passed by reference) + */ + private function processExternalPlugins(array $richtextConfiguration, array &$configuration): void + { + $externalPlugins = $richtextConfiguration['editor']['externalPlugins'] ?? []; + + if ($externalPlugins === []) { + return; + } + + foreach ($externalPlugins as $pluginName => $pluginConfig) { + $configName = $pluginConfig['configName'] ?? $pluginName; + + if (isset($pluginConfig['route'])) { + $pluginConfig['routeUrl'] = $this->buildPluginRouteUrl($pluginConfig['route']); + } + + unset($pluginConfig['route'], $pluginConfig['configName'], $pluginConfig['resource']); + + if ($pluginConfig !== []) { + if (!isset($configuration[$configName])) { + $configuration[$configName] = $pluginConfig; + } elseif (is_array($configuration[$configName])) { + $configuration[$configName] = array_replace_recursive( + $pluginConfig, + $configuration[$configName] + ); + } + } + } + } + + /** + * Builds the route URL for an external plugin. + * + * @param string $route The route identifier (e.g., 'rteckeditor_wizard_browse_links') + * @return string The complete URL for the route + */ + private function buildPluginRouteUrl(string $route): string + { + // Build URL parameters for the route + // Using dummy values for form editor context as we don't have a specific record + $urlParameters = [ + 'P' => [ + 'table' => 'tx_form', + 'uid' => 0, + 'fieldName' => 'form_field', + 'recordType' => '', + 'pid' => 0, + 'richtextConfigurationName' => '', + ], + ]; + + return (string)$this->uriBuilder->buildUriFromRoute($route, $urlParameters); + } + + /** + * Configures language settings for the editor. + * + * Sets both UI language (based on backend user preference) and content language. + * For the form editor context, content language is always set to 'en'. + * + * @param array $configuration The configuration array to modify (passed by reference) + */ + private function configureLanguage(array &$configuration): void + { + // Set the UI language of the editor + if (empty($configuration['language']) + || (is_array($configuration['language']) && empty($configuration['language']['ui'])) + ) { + $userLang = (string)($this->getBackendUser()->user['lang'] ?? 'en'); + $configuration['language']['ui'] = $userLang === 'default' ? 'en' : $userLang; + } elseif (!is_array($configuration['language'])) { + // Convert string language config to array format + $configuration['language'] = [ + 'ui' => $configuration['language'], + ]; + } + + // Set content language to 'en' for form editor (no specific content language context) + $configuration['language']['content'] = 'en'; + } + + /** + * Replaces LLL: language references with translated values. + * + * Recursively processes the configuration array and translates all language labels. + * + * @param array $configuration The configuration to process + * @return array The configuration with translated labels + */ + private function replaceLanguageFileReferences(array $configuration): array + { + foreach ($configuration as $key => $value) { + if (is_array($value)) { + $configuration[$key] = $this->replaceLanguageFileReferences($value); + } elseif (is_string($value) && str_starts_with($value, 'LLL:')) { + $configuration[$key] = $this->getLanguageService()->sL($value); + } + } + return $configuration; + } + + /** + * Replaces absolute EXT: paths with relative web paths. + * + * Recursively processes the configuration array and converts all EXT: paths + * to publicly accessible web paths. + * + * @param array $configuration The configuration to process + * @return array The configuration with resolved paths + */ + private function replaceAbsolutePathsToRelativeResourcesPath(array $configuration): array + { + foreach ($configuration as $key => $value) { + if (is_array($value)) { + $configuration[$key] = $this->replaceAbsolutePathsToRelativeResourcesPath($value); + } elseif ( + is_string($value) + && $value !== '' + && PathUtility::isExtensionPath(strtoupper($value), true) + ) { + $configuration[$key] = $this->resolveUrlPath($value); + } + } + return $configuration; + } + + /** + * Resolves a system resource to an absolute web URL. + * + * @param string $value The resource path (e.g., 'EXT:my_extension/Resources/Public/Css/file.css') + * @return string The public web URL to the resource + */ + private function resolveUrlPath(string $value): string + { + $resource = $this->systemResourceFactory->createPublicResource($value); + return (string)$this->resourcePublisher->generateUri($resource, null); + } + + private function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + private function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Service/TranslationService.php b/Classes/Service/TranslationService.php new file mode 100644 index 0000000..05812c5 --- /dev/null +++ b/Classes/Service/TranslationService.php @@ -0,0 +1,583 @@ +getRequest(); + $languageService = $this->createLanguageService($locale, $request); + + if (!empty($locallangPathAndFilename) && $request) { + $this->applyTypoScriptOverrides($languageService, $locallangPathAndFilename, $request); + } + + $fullReference = !empty($locallangPathAndFilename) ? $locallangPathAndFilename . ':' . $key : $key; + $value = $languageService->label($fullReference, $arguments ?? []); + return $value ?? $defaultValue; + } + + /** + * Recursively translate values. + * + * @return array the modified array + * @internal + */ + public function translateValuesRecursive(array $array, array $translationFiles = []): array + { + $result = $array; + foreach ($result as $key => $value) { + if (is_array($value)) { + $result[$key] = $this->translateValuesRecursive($value, $translationFiles); + } else { + $translationFiles = $this->sortArrayWithIntegerKeysDescending($translationFiles); + + if (!empty($translationFiles)) { + foreach ($translationFiles as $translationFile) { + $translatedValue = $this->translate($value, null, $translationFile, null); + if (!empty($translatedValue)) { + $result[$key] = $translatedValue; + break; + } + } + } else { + $result[$key] = $this->translate($value, null, null, null, $value); + } + } + } + return $result; + } + + /** + * @return array the modified array + * @internal + */ + public function translateToAllBackendLanguages( + string $key, + ?array $arguments = null, + array $translationFiles = [] + ): array { + $result = []; + $translationFiles = $this->sortArrayWithIntegerKeysDescending($translationFiles); + + foreach ($this->locales->getActiveLanguages() as $language) { + $result[$language] = $key; + foreach ($translationFiles as $translationFile) { + $translatedValue = $this->translate($key, $arguments, $translationFile, $language, $key); + if ($translatedValue !== $key) { + $result[$language] = $translatedValue; + break; + } + } + } + + return $result; + } + + /** + * @throws \InvalidArgumentException + */ + public function translateFinisherOption( + FormRuntime $formRuntime, + string $finisherIdentifier, + string $optionKey, + string $optionValue, + array $renderingOptions = [] + ): string { + if (empty($finisherIdentifier)) { + throw new \InvalidArgumentException('The argument "finisherIdentifier" is empty', 1476216059); + } + if (empty($optionKey)) { + throw new \InvalidArgumentException('The argument "optionKey" is empty', 1476216060); + } + + if (in_array($optionKey, $renderingOptions['propertiesExcludedFromTranslation'] ?? [], true)) { + return $optionValue; + } + + $finisherIdentifier = preg_replace('/Finisher$/', '', $finisherIdentifier); + $translationFiles = $renderingOptions['translationFiles'] ?? []; + if (empty($translationFiles)) { + $translationFiles = $formRuntime->getRenderingOptions()['translation']['translationFiles']; + } + + $translationFiles = $this->sortArrayWithIntegerKeysDescending($translationFiles); + + if (isset($renderingOptions['translatePropertyValueIfEmpty'])) { + $translatePropertyValueIfEmpty = (bool)$renderingOptions['translatePropertyValueIfEmpty']; + } else { + $translatePropertyValueIfEmpty = true; + } + + if (empty($optionValue) && !$translatePropertyValueIfEmpty) { + return $optionValue; + } + + $locale = null; + if (isset($renderingOptions['language'])) { + $locale = $renderingOptions['language']; + } + + try { + $arguments = ArrayUtility::getValueByPath($renderingOptions['arguments'] ?? [], $optionKey, '.'); + } catch (MissingArrayPathException $e) { + $arguments = []; + } + + $originalFormIdentifier = null; + if (isset($formRuntime->getRenderingOptions()['_originalIdentifier'])) { + $originalFormIdentifier = $formRuntime->getRenderingOptions()['_originalIdentifier']; + } + + $translationKeyChain = $this->keychainBuilder->buildForFinisherOption( + $translationFiles, + $formRuntime->getIdentifier(), + $finisherIdentifier, + $optionKey, + $originalFormIdentifier + ); + + $translatedValue = $this->processTranslationChain($translationKeyChain, $locale, $arguments); + $translatedValue = $this->isEmptyTranslatedValue($translatedValue) ? $optionValue : $translatedValue; + + return $translatedValue; + } + + /** + * @throws \InvalidArgumentException + * @internal + */ + public function translateFormElementValue( + RootRenderableInterface $element, + array $propertyParts, + FormRuntime $formRuntime, + Locale|string|null $locale = null, + ): array|string|null { + if (empty($propertyParts)) { + throw new \InvalidArgumentException('The argument "propertyParts" is empty', 1476216007); + } + + $propertyType = 'properties'; + $property = implode('.', $propertyParts); + $renderingOptions = $element->getRenderingOptions(); + + if ($property === 'label') { + $defaultValue = $element->getLabel(); + } elseif ($property === 'defaultValue' && $element instanceof FormElementInterface) { + $defaultValue = $element->getDefaultValue(); + } else { + if ($element instanceof FormElementInterface) { + try { + $defaultValue = ArrayUtility::getValueByPath($element->getProperties(), $propertyParts, '.'); + } catch (MissingArrayPathException $exception) { + $defaultValue = null; + } + } else { + $propertyType = 'renderingOptions'; + try { + $defaultValue = ArrayUtility::getValueByPath($renderingOptions, $propertyParts, '.'); + } catch (MissingArrayPathException $exception) { + $defaultValue = null; + } + } + } + + if (isset($renderingOptions['translation']['translatePropertyValueIfEmpty'])) { + $translatePropertyValueIfEmpty = $renderingOptions['translation']['translatePropertyValueIfEmpty']; + } else { + $translatePropertyValueIfEmpty = true; + } + + if ($this->isEmptyTranslatedValue($defaultValue) && !$translatePropertyValueIfEmpty) { + return $defaultValue; + } + + $defaultValue = $this->isEmptyTranslatedValue($defaultValue) ? '' : $defaultValue; + $translationFiles = $renderingOptions['translation']['translationFiles'] ?? []; + if (empty($translationFiles)) { + $translationFiles = $formRuntime->getRenderingOptions()['translation']['translationFiles']; + } + + $translationFiles = $this->sortArrayWithIntegerKeysDescending($translationFiles); + + if (!$locale && isset($renderingOptions['translation']['language'])) { + $locale = $renderingOptions['translation']['language']; + } + + try { + $arguments = ArrayUtility::getValueByPath($renderingOptions['translation']['arguments'] ?? [], $propertyParts, '.'); + } catch (MissingArrayPathException $e) { + $arguments = []; + } + + $originalFormIdentifier = null; + if (isset($formRuntime->getRenderingOptions()['_originalIdentifier'])) { + $originalFormIdentifier = $formRuntime->getRenderingOptions()['_originalIdentifier']; + } + + $elementIsFormRuntime = $element instanceof FormRuntime; + $elementIdentifier = $element->getIdentifier(); + $elementType = $element->getType(); + + if ($property === 'options' && is_array($defaultValue)) { + foreach ($defaultValue as $optionValue => &$optionLabel) { + if ($elementIsFormRuntime) { + $translationKeyChain = $this->keychainBuilder->buildForFormRuntimeOption( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $property, + $optionValue, + $originalFormIdentifier + ); + } else { + $translationKeyChain = $this->keychainBuilder->buildForElementOption( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $property, + $optionValue, + $originalFormIdentifier + ); + } + + $translatedValue = $this->processTranslationChain($translationKeyChain, $locale, $arguments); + $optionLabel = $this->isEmptyTranslatedValue($translatedValue) ? $optionLabel : $translatedValue; + } + $translatedValue = $defaultValue; + } elseif ($property === 'fluidAdditionalAttributes') { + // "fluidAdditionalAttributes" is a globally available property and is used across all built-in + // form templates. However, it's not necessarily defined in the form configuration. This can lead to + // an empty string as default value, which is invalid. This check makes sure that an array is returned + // even if the property is not defined. + if (!is_array($defaultValue)) { + $defaultValue = []; + } + foreach ($defaultValue as $propertyName => &$propertyValue) { + if ($elementIsFormRuntime) { + $translationKeyChain = $this->keychainBuilder->buildForFormRuntimeProperty( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $propertyName, + $originalFormIdentifier + ); + } else { + $translationKeyChain = $this->keychainBuilder->buildForElementProperty( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $propertyName, + $originalFormIdentifier + ); + } + + $translatedValue = $this->processTranslationChain($translationKeyChain, $locale, $arguments); + $propertyValue = $this->isEmptyTranslatedValue($translatedValue) ? $propertyValue : $translatedValue; + } + $translatedValue = $defaultValue; + } else { + if ($elementIsFormRuntime) { + $translationKeyChain = $this->keychainBuilder->buildForFormRuntimeProperty( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $property, + $originalFormIdentifier + ); + } else { + $translationKeyChain = $this->keychainBuilder->buildForElementProperty( + $translationFiles, + $formRuntime->getIdentifier(), + $elementIdentifier, + $elementType, + $propertyType, + $property, + $originalFormIdentifier + ); + } + + $translatedValue = $this->processTranslationChain($translationKeyChain, $locale, $arguments); + $translatedValue = $this->isEmptyTranslatedValue($translatedValue) ? $defaultValue : $translatedValue; + } + + return $translatedValue; + } + + /** + * @throws \InvalidArgumentException + * @internal + */ + public function translateFormElementError( + RootRenderableInterface $element, + int $code, + array $arguments, + string $defaultValue, + FormRuntime $formRuntime + ): string { + if (empty($code)) { + throw new \InvalidArgumentException('The argument "code" is empty', 1489272978); + } + + if ($element instanceof FormElementInterface) { + $validationErrors = $element->getProperties()['validationErrorMessages'] ?? null; + if (is_array($validationErrors)) { + foreach ($validationErrors as $validationError) { + if ((int)$validationError['code'] === $code) { + return sprintf($validationError['message'], ...$arguments); + } + } + } + } + + $renderingOptions = $element->getRenderingOptions(); + $translationFiles = $renderingOptions['translation']['translationFiles'] ?? []; + if (empty($translationFiles)) { + $translationFiles = $formRuntime->getRenderingOptions()['translation']['translationFiles']; + } + + $translationFiles = $this->sortArrayWithIntegerKeysDescending($translationFiles); + + $locale = null; + if (isset($renderingOptions['language'])) { + $locale = $renderingOptions['language']; + } + + $originalFormIdentifier = null; + if (isset($formRuntime->getRenderingOptions()['_originalIdentifier'])) { + $originalFormIdentifier = $formRuntime->getRenderingOptions()['_originalIdentifier']; + } + + if ($element instanceof FormRuntime) { + $translationKeyChain = $this->keychainBuilder->buildForFormRuntimeValidationError( + $translationFiles, + $formRuntime->getIdentifier(), + $element->getIdentifier(), + $code, + $originalFormIdentifier + ); + } else { + $translationKeyChain = $this->keychainBuilder->buildForValidationError( + $translationFiles, + $formRuntime->getIdentifier(), + $element->getIdentifier(), + $code, + $originalFormIdentifier + ); + } + + $translatedValue = $this->processTranslationChain($translationKeyChain, $locale, $arguments); + $translatedValue = $this->isEmptyTranslatedValue($translatedValue) ? $defaultValue : $translatedValue; + return $translatedValue; + } + + /** + * @return string|\Stringable|null + */ + protected function processTranslationChain( + array $translationKeyChain, + Locale|string|null $locale = null, + ?array $arguments = null + ) { + $request = $this->getRequest(); + $languageService = $this->createLanguageService($locale, $request); + $appliedOverridesForFiles = []; + + foreach ($translationKeyChain as $translationKey) { + if ($request) { + $fileRef = $this->extractFileReferenceFromKey($translationKey); + if ($fileRef !== '' && !isset($appliedOverridesForFiles[$fileRef])) { + $this->applyTypoScriptOverrides($languageService, $fileRef, $request); + $appliedOverridesForFiles[$fileRef] = true; + } + } + $translatedValue = $languageService->label($translationKey, $arguments ?? []); + if (!$this->isEmptyTranslatedValue($translatedValue)) { + return $translatedValue; + } + } + return null; + } + + /** + * If the array contains numerical keys only, sort it in descending order + */ + protected function sortArrayWithIntegerKeysDescending(array $array): array + { + if (count(array_filter(array_keys($array), 'is_string')) === 0) { + krsort($array); + } + return $array; + } + + /** + * Check if given translated value is considered "empty". + * + * A translated value is considered "empty" if it's either NULL or + * an empty string. This helper method exists to perform a less strict + * check than the native {@see empty()} function, because it is too + * strict in terms of supported translated values. For example, the + * value "0" is valid, whereas {@see empty()} would handle it as "empty" + * and therefore invalid. + */ + protected function isEmptyTranslatedValue(mixed $translatedValue): bool + { + if ($translatedValue === null) { + return true; + } + + if (is_string($translatedValue)) { + return trim($translatedValue) === ''; + } + + if (is_bool($translatedValue)) { + return !$translatedValue; + } + + if (is_array($translatedValue)) { + return $translatedValue === []; + } + + return false; + } + + /** + * Creates a LanguageService for the given locale or the locale from the current request. + * Returns a LanguageService (which implements TranslatorInterface) rather than the interface + * directly, since TypoScript label overrides require LanguageService-specific methods. + */ + private function createLanguageService(Locale|string|null $locale, ?ServerRequestInterface $request): LanguageService + { + if ($locale) { + return $this->languageServiceFactory->create($locale); + } + return $this->languageServiceFactory->create($this->locales->createLocaleFromRequest($request)); + } + + /** + * Applies TypoScript label overrides (plugin.tx_form._LOCAL_LANG) to the given language + * service for the specified file reference, if a frontend TypoScript setup is present. + */ + private function applyTypoScriptOverrides(LanguageService $languageService, string $fileRef, ServerRequestInterface $request): void + { + $typoScript = $request->getAttribute('frontend.typoscript'); + if ($typoScript instanceof FrontendTypoScript && $typoScript->hasSetup()) { + $overrideLabels = $languageService->loadTypoScriptLabelsFromExtension('form', $typoScript); + if ($overrideLabels !== []) { + $languageService->overrideLabels($fileRef, $overrideLabels); + } + } + } + + /** + * Extracts the file reference (domain) part from a full translation key reference such as + * 'EXT:my_ext/path/file.xlf:my.key' or 'LLL:EXT:my_ext/path/file.xlf:my.key'. + * Returns an empty string when no file reference can be determined. + */ + private function extractFileReferenceFromKey(string $key): string + { + $strippedKey = str_starts_with($key, 'LLL:') ? substr($key, 4) : $key; + $keyParts = explode(':', $strippedKey); + if (PathUtility::isExtensionPath($strippedKey)) { + // e.g. EXT:my_ext/path/file.xlf -> keyParts[0]='EXT', keyParts[1]='my_ext/path/file.xlf' + return $keyParts[0] . ':' . ($keyParts[1] ?? ''); + } + // Semantic domain, e.g. 'my.domain:my.key' -> 'my.domain' + return $keyParts[0]; + } + + private function getRequest(): ?ServerRequestInterface + { + return $GLOBALS['TYPO3_REQUEST'] ?? null; + } +} diff --git a/Classes/Slot/FilePersistenceSlot.php b/Classes/Slot/FilePersistenceSlot.php new file mode 100644 index 0000000..9c9343b --- /dev/null +++ b/Classes/Slot/FilePersistenceSlot.php @@ -0,0 +1,187 @@ +hashService->hmac($content, self::class); + } + + /** + * Allows invocation for a particular combination of command and file + * identifier. Commands providing new content have to submit a HMAC + * signature on the content as well. + * + * @see getContentSignature + */ + public function allowInvocation(string $command, string $combinedFileIdentifier, ?string $contentSignature = null): bool + { + $index = $this->searchAllowedInvocation($command, $combinedFileIdentifier, $contentSignature); + if ($index !== null) { + return false; + } + $this->allowedInvocations[] = [ + 'command' => $command, + 'combinedFileIdentifier' => $combinedFileIdentifier, + 'contentSignature' => $contentSignature, + ]; + return true; + } + + #[AsEventListener('form-framework/creation')] + public function onPreFileCreate(BeforeFileCreatedEvent $event): void + { + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getFolder(), $event->getFileName()); + $this->assertFileName(self::COMMAND_FILE_CREATE, $combinedFileIdentifier); + } + + #[AsEventListener('form-framework/add')] + public function onPreFileAdd(BeforeFileAddedEvent $event): void + { + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getTargetFolder(), $event->getFileName()); + // While assertFileName() below also checks if it's a form definition + // we want an early return here to not file_get_contents() below which + // would be triggered on every file add() command otherwise. + if (!$this->isFormDefinition($combinedFileIdentifier)) { + return; + } + $this->assertFileName(self::COMMAND_FILE_ADD, $combinedFileIdentifier, (string)file_get_contents($event->getSourceFilePath())); + } + + #[AsEventListener('form-framework/rename')] + public function onPreFileRename(BeforeFileRenamedEvent $event): void + { + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getFile()->getParentFolder(), $event->getTargetFileName() ?? ''); + $this->assertFileName(self::COMMAND_FILE_RENAME, $combinedFileIdentifier); + } + + #[AsEventListener('form-framework/replace')] + public function onPreFileReplace(BeforeFileReplacedEvent $event): void + { + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getFile()->getParentFolder(), $event->getFile()->getName()); + $this->assertFileName(self::COMMAND_FILE_REPLACE, $combinedFileIdentifier); + } + + #[AsEventListener('form-framework/move')] + public function onPreFileMove(BeforeFileMovedEvent $event): void + { + // Skip check, in case file extension would not change during this + // command. In case e.g. "file.txt" shall be renamed to "file.form.yaml" + // the invocation still has to be granted. + // Any file moved to a recycle folder is accepted as well. + if ($this->isFormDefinition($event->getFile()->getIdentifier()) + && $this->isFormDefinition($event->getTargetFileName()) + || $this->isRecycleFolder($event->getFolder())) { + return; + } + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getFolder(), $event->getTargetFileName()); + $this->assertFileName(self::COMMAND_FILE_MOVE, $combinedFileIdentifier); + } + + #[AsEventListener('form-framework/update-content')] + public function onPreFileSetContents(BeforeFileContentsSetEvent $event): void + { + $combinedFileIdentifier = $this->buildCombinedIdentifier($event->getFile()->getParentFolder(), $event->getFile()->getName()); + $this->assertFileName(self::COMMAND_FILE_SET_CONTENTS, $combinedFileIdentifier, $event->getContent()); + } + + /** + * @throws FormDefinitionPersistenceException + */ + private function assertFileName(string $command, string $combinedFileIdentifier, ?string $content = null): void + { + if (!$this->isFormDefinition($combinedFileIdentifier)) { + return; + } + $contentSignature = null; + if ($content !== null) { + $contentSignature = $this->getContentSignature($content); + } + $allowedInvocationIndex = $this->searchAllowedInvocation($command, $combinedFileIdentifier, $contentSignature); + if ($allowedInvocationIndex === null) { + throw new FormDefinitionPersistenceException( + sprintf('Persisting form definition "%s" is denied', $combinedFileIdentifier), + 1530281202 + ); + } + unset($this->allowedInvocations[$allowedInvocationIndex]); + } + + private function searchAllowedInvocation(string $command, string $combinedFileIdentifier, ?string $contentSignature = null): ?int + { + foreach ($this->allowedInvocations as $index => $allowedInvocation) { + if ($command === $allowedInvocation['command'] + && $combinedFileIdentifier === $allowedInvocation['combinedFileIdentifier'] + && $contentSignature === $allowedInvocation['contentSignature'] + ) { + return $index; + } + } + return null; + } + + private function buildCombinedIdentifier(FolderInterface $folder, string $fileName): string + { + return sprintf('%d:%s%s', $folder->getStorage()->getUid(), $folder->getIdentifier(), $fileName); + } + + private function isFormDefinition(string $identifier): bool + { + return str_ends_with( + mb_strtolower($identifier), + FormPersistenceManagerInterface::FORM_DEFINITION_FILE_EXTENSION + ); + } + + private function isRecycleFolder(FolderInterface $folder): bool + { + $role = $folder->getStorage()->getRole($folder); + return $role === FolderInterface::ROLE_RECYCLER; + } +} diff --git a/Classes/Slot/FormDefinitionPersistenceException.php b/Classes/Slot/FormDefinitionPersistenceException.php new file mode 100644 index 0000000..d4d6504 --- /dev/null +++ b/Classes/Slot/FormDefinitionPersistenceException.php @@ -0,0 +1,24 @@ + + */ + protected $fileIdentifiers = []; + + public function __construct(private readonly HashService $hashService) {} + + #[AsEventListener('form-framework/resource-getPublicUrl')] + public function getPublicUrl(GeneratePublicUrlForResourceEvent $event): void + { + $resource = $event->getResource(); + if (!$resource instanceof FileInterface + || !$this->has($resource) + || $event->getStorage()->getDriverType() !== 'Local' + ) { + return; + } + $event->setPublicUrl($this->getStreamUrl($event->getResource())); + } + + public function add(FileInterface $resource): void + { + if ($this->has($resource)) { + return; + } + $this->fileIdentifiers[] = $resource->getIdentifier(); + } + + public function has(FileInterface $resource): bool + { + return in_array($resource->getIdentifier(), $this->fileIdentifiers, true); + } + + protected function getStreamUrl(ResourceInterface $resource): string + { + $queryParameterArray = ['eID' => 'dumpFile', 't' => '']; + if ($resource instanceof File) { + $queryParameterArray['f'] = $resource->getUid(); + $queryParameterArray['t'] = 'f'; + } elseif ($resource instanceof ProcessedFile) { + $queryParameterArray['p'] = $resource->getUid(); + $queryParameterArray['t'] = 'p'; + } + + $queryParameterArray['token'] = $this->hashService->hmac(implode('|', $queryParameterArray), 'resourceStorageDumpFile'); + $publicUrl = ''; + if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface) { + $publicUrl = GeneralUtility::locationHeaderUrl(PathUtility::getAbsoluteWebPath(Environment::getPublicPath() . '/index.php'), $GLOBALS['TYPO3_REQUEST']); + } + $publicUrl .= '?' . http_build_query($queryParameterArray, '', '&', PHP_QUERY_RFC3986); + return $publicUrl; + } +} diff --git a/Classes/SoftReference/FormPersistenceIdentifierSoftReferenceParser.php b/Classes/SoftReference/FormPersistenceIdentifierSoftReferenceParser.php new file mode 100644 index 0000000..a596995 --- /dev/null +++ b/Classes/SoftReference/FormPersistenceIdentifierSoftReferenceParser.php @@ -0,0 +1,116 @@ +setTokenIdBasePrefix($table, (string)$uid, $field, $structurePath); + $tokenId = $this->makeTokenID($content); + + // Handle extension paths (EXT:extension_key/...) + if (PathUtility::isExtensionPath($content)) { + return $this->createResultForExtensionReference($content, $tokenId); + } + + // Handle numeric database identifiers (uid) + if (MathUtility::canBeInterpretedAsInteger($content)) { + return $this->createResultForDatabaseReference($content, $tokenId); + } + + // Handle file storage identifiers (storage:/path) + try { + $file = $this->resourceFactory->retrieveFileOrFolderObject($content); + } catch (\Exception $e) { + // Top level catch to ensure useful following exception handling, because FAL throws top level exceptions. + // TYPO3\CMS\Core\Database\ReferenceIndex::getRelations() will check the return value of this hook with is_array() + // so we return null to tell getRelations() to do nothing. + return SoftReferenceParserResult::createWithoutMatches(); + } + + if ($file === null) { + return SoftReferenceParserResult::createWithoutMatches(); + } + + return SoftReferenceParserResult::create('{softref:' . $tokenId . '}', [ + $tokenId => [ + 'matchString' => $content, + 'subst' => [ + 'type' => 'db', + 'recordRef' => 'sys_file:' . $file->getUid(), + 'tokenID' => $tokenId, + 'tokenValue' => $content, + ], + ], + ]); + } + + private function createResultForExtensionReference(string $extensionReference, string $tokenId): SoftReferenceParserResult + { + return SoftReferenceParserResult::create('{softref:' . $tokenId . '}', [ + $tokenId => [ + 'matchString' => $extensionReference, + 'subst' => [ + 'type' => 'string', + 'tokenID' => $tokenId, + 'tokenValue' => $extensionReference, + ], + ], + ]); + } + + /** + * Create soft reference result for database identifiers (numeric uid) + * These are stored as db references in sys_refindex for tracking usage + */ + private function createResultForDatabaseReference(string $databaseReference, string $tokenId): SoftReferenceParserResult + { + return SoftReferenceParserResult::create('{softref:' . $tokenId . '}', [ + $tokenId => [ + 'matchString' => $databaseReference, + 'subst' => [ + 'type' => 'db', + 'recordRef' => FormDefinitionRepository::TABLE_NAME . ':' . $databaseReference, + 'tokenID' => $tokenId, + 'tokenValue' => $databaseReference, + ], + ], + ]); + } +} diff --git a/Classes/Storage/AbstractFileStorageAdapter.php b/Classes/Storage/AbstractFileStorageAdapter.php new file mode 100644 index 0000000..35eb4f4 --- /dev/null +++ b/Classes/Storage/AbstractFileStorageAdapter.php @@ -0,0 +1,173 @@ +storageRepository = $storageRepository; + } + + protected function hasValidFileExtension(string $identifier): bool + { + return str_ends_with($identifier, self::FORM_DEFINITION_FILE_EXTENSION); + } + + abstract public function exists(FormIdentifier $identifier): bool; + abstract public function existsByFormIdentifier(string $formIdentifier): bool; + abstract public function findAll(SearchCriteria $criteria): array; + + /** + * Build a user-friendly storageLocation label for display + * Each storage adapter implements this to provide appropriate storageLocation information + */ + abstract protected function buildStorageLocationLabel(string $persistenceIdentifier): string; + + /** + * This takes a form identifier and returns a unique persistence identifier for it. + * By default, this is just similar to the identifier. But if a form with the same persistence identifier already + * exists a suffix is appended until the persistence identifier is unique. + * + * @param string $formIdentifier lowerCamelCased form identifier + * @param string $storageLocation Path where the form should be saved (e.g., "1:/forms/") + * @return string unique form persistence identifier (e.g., "1:/forms/contact.form.yaml") + * @throws NoUniquePersistenceIdentifierException + * @throws PersistenceManagerException + */ + public function getUniquePersistenceIdentifier(string $formIdentifier, string $storageLocation): string + { + $storageLocation = rtrim($storageLocation, '/') . '/'; + $formPersistenceIdentifier = $storageLocation . $formIdentifier . self::FORM_DEFINITION_FILE_EXTENSION; + + if (!$this->exists(new FormIdentifier($formPersistenceIdentifier))) { + return $formPersistenceIdentifier; + } + + for ($attempts = 1; $attempts < 100; $attempts++) { + $formPersistenceIdentifier = $storageLocation . sprintf('%s_%d', $formIdentifier, $attempts) . self::FORM_DEFINITION_FILE_EXTENSION; + if (!$this->exists(new FormIdentifier($formPersistenceIdentifier))) { + return $formPersistenceIdentifier; + } + } + + $formPersistenceIdentifier = $storageLocation . sprintf('%s_%d', $formIdentifier, time()) . self::FORM_DEFINITION_FILE_EXTENSION; + if (!$this->exists(new FormIdentifier($formPersistenceIdentifier))) { + return $formPersistenceIdentifier; + } + + throw new NoUniquePersistenceIdentifierException( + sprintf('Could not find a unique persistence identifier for form identifier "%s" after %d attempts', $formIdentifier, $attempts), + 1764879439 + ); + } + + protected function extractMetaDataFromCouldBeFormDefinition(string $maybeRawFormDefinition): array + { + $metaDataProperties = ['identifier', 'type', 'label', 'prototypeName']; + $metaData = []; + foreach (explode(LF, $maybeRawFormDefinition) as $line) { + if (empty($line) || $line[0] === ' ') { + continue; + } + $parts = explode(':', $line, 2); + $key = trim($parts[0]); + if (!($parts[1] ?? null) || !in_array($key, $metaDataProperties, true)) { + continue; + } + if ($key === 'label') { + try { + $parsedLabelLine = Yaml::parse($line); + $value = $parsedLabelLine['label'] ?? ''; + } catch (ParseException) { + $value = ''; + } + } else { + $value = trim($parts[1], " '\"\r"); + } + $metaData[$key] = $value; + } + return $metaData; + } + + /** + * @throws PersistenceManagerException + */ + protected function generateErrorsIfFormDefinitionIsInvalidOrHasInvalidFileExtension(array $formDefinition, string $identifier): void + { + if (!$this->looksLikeAFormDefinitionArray($formDefinition) || !$this->hasValidFileExtension($identifier)) { + throw new PersistenceManagerException(sprintf('Form definition "%s" does not end with ".form.yaml".', $identifier), 1531160649); + } + } + + /** + * Check if array looks like a form definition + */ + protected function looksLikeAFormDefinitionArray(array $data): bool + { + return !empty($data['identifier']) && trim($data['type'] ?? '') === 'Form'; + } + + protected function looksLikeAFormDefinition(FormMetadata $formMetadata): bool + { + return !empty($formMetadata->identifier) && trim($formMetadata->type) === 'Form'; + } + + /** + * Check if form data matches search criteria + */ + protected function matchesCriteria(FormMetadata $formMetadata, SearchCriteria $criteria): bool + { + if ($criteria->searchTerm) { + $searchIn = strtolower( + $formMetadata->name . ' ' + . $formMetadata->identifier . ' ' + . $formMetadata->prototypeName . ' ' + . ($formMetadata->persistenceIdentifier ?? '') + ); + + if (!str_contains($searchIn, strtolower($criteria->searchTerm))) { + return false; + } + } + + return true; + } +} diff --git a/Classes/Storage/DatabaseStorageAdapter.php b/Classes/Storage/DatabaseStorageAdapter.php new file mode 100644 index 0000000..a69ff85 --- /dev/null +++ b/Classes/Storage/DatabaseStorageAdapter.php @@ -0,0 +1,352 @@ +extractUidFromIdentifier($identifier); + + $record = $this->repository->findByUid($uid); + if (!$record) { + throw new PersistenceManagerException( + sprintf('The form with uid "%s" could not be loaded.', $uid), + 1767199422 + ); + } + + $applicationType = $request !== null ? ApplicationType::fromRequest($request) : null; + // Skip permission checks in frontend context: Forms must be readable without a + // backend user session, so no backend permission checks are applied for frontend + // requests. In all other contexts (e.g. backend), permission checks are enforced. + if (!$applicationType?->isFrontend()) { + $this->permissionChecker->assertReadAccessForRecord($uid, $record); + } + + try { + $formDefinitionArray = json_decode($record['configuration'] ?? '', true, flags: JSON_THROW_ON_ERROR); + } catch (\JsonException $e) { + throw new PersistenceManagerException( + sprintf('The form definition for uid "%s" is invalid: %s', $uid, $e->getMessage()), + 1767199423, + $e + ); + } + + if (!is_array($formDefinitionArray)) { + throw new PersistenceManagerException( + sprintf('The form definition for uid "%s" is invalid.', $uid), + 1767199444 + ); + } + + $formDefinitionArray = $this->jsonObjectKeyOrderPreserver->restore($formDefinitionArray); + $formDefinitionArray['identifier'] = $record['identifier']; + + return FormData::fromArray($formDefinitionArray); + } + + /** + * @throws PersistenceManagerException + */ + public function write(FormIdentifier $identifier, FormData $data, ?StorageContext $context = null): FormIdentifier + { + if (!$this->exists($identifier)) { + $pid = 0; + + if (!$this->permissionChecker->hasWritePermission($pid)) { + throw new PersistenceManagerException( + 'Access denied: You do not have permission to create a form.', + 1767199435 + ); + } + + $uid = $this->repository->add($identifier->identifier, $pid, $data); + + if (!$uid) { + throw new PersistenceManagerException( + 'Failed to create form definition in database.', + 1767199424 + ); + } + + return new FormIdentifier((string)$uid); + } + + $uid = $this->extractUidFromIdentifier($identifier); + + $record = $this->repository->findByUid($uid); + if (!$record) { + throw new PersistenceManagerException( + sprintf('The form with uid "%s" could not be found.', $uid), + 1767199425 + ); + } + + $this->permissionChecker->assertWriteAccessForRecord($uid, $record); + + $result = $this->repository->update($uid, $data); + + if (!$result) { + throw new PersistenceManagerException( + sprintf('Failed to update form definition with uid "%s".', $uid), + 1767199426 + ); + } + + return $identifier; + } + + /** + * @throws PersistenceManagerException + */ + public function delete(FormIdentifier $identifier): void + { + $uid = $this->extractUidFromIdentifier($identifier); + + $record = $this->repository->findByUid($uid); + if (!$record) { + throw new PersistenceManagerException( + sprintf('The form with uid "%s" could not be found.', $uid), + 1767199431 + ); + } + + $this->permissionChecker->assertWriteAccessForRecord($uid, $record); + + $success = $this->repository->remove($uid); + + if (!$success) { + throw new PersistenceManagerException( + sprintf('Failed to delete form definition with uid "%s".', $uid), + 1767199427 + ); + } + } + + /** + * @throws PersistenceManagerException + */ + public function exists(FormIdentifier $identifier): bool + { + if (str_starts_with($identifier->identifier, 'NEW')) { + return false; + } + + $uid = $this->extractUidFromIdentifier($identifier); + $record = $this->repository->findByUid($uid); + + if ($record === null) { + return false; + } + + $pid = (int)($record['pid'] ?? -1); + return $this->permissionChecker->hasReadPermission($pid); + } + + public function existsByFormIdentifier(string $formIdentifier): bool + { + return $this->repository->existsByFormIdentifier($formIdentifier); + } + + /** + * Find all form definitions for listing. + * + * Uses findAllForListing() which only selects metadata columns (uid, pid, identifier, label) + * instead of the full configuration JSON. This avoids loading and parsing potentially large + * JSON blobs just for the form listing view. + */ + public function findAll(SearchCriteria $criteria): array + { + $rows = $this->repository->findAllForListing($criteria); + + $results = []; + foreach ($rows as $row) { + if ($row['uid'] === null) { + continue; + } + + $pageId = (int)($row['pid'] ?? 0); + $uid = (int)$row['uid']; + + if (!$this->permissionChecker->hasReadPermission($pageId)) { + continue; + } + + $persistenceIdentifier = (string)$uid; + + $hasWritePermission = $this->permissionChecker->hasWritePermission($pageId); + $metadata = new FormMetadata( + identifier: $row['identifier'] ?? '', + type: 'Form', + name: $row['label'] ?? $row['identifier'] ?? '', + prototypeName: 'standard', + persistenceIdentifier: $persistenceIdentifier, + readOnly: !$hasWritePermission, + removable: $hasWritePermission, + fileUid: null, + storageLocation: $this->getStorageLocationLabel(), + ); + + $results[] = $metadata; + } + + return $results; + } + + public function getFormManagerOptions(): array + { + if (!$this->permissionChecker->hasWritePermission(0)) { + return []; + } + + return [ + 'allowedStorageLocations' => [ + [ + 'value' => '0', + 'label' => $this->getStorageLocationLabel(), + ], + ], + ]; + } + + public function isAccessible(): bool + { + return $this->permissionChecker->hasWritePermission(0); + } + + public function isAllowedStorageLocation(string $storageLocation): bool + { + if (MathUtility::canBeInterpretedAsInteger($storageLocation)) { + return (int)$storageLocation === 0; + } + + return false; + } + + public function isAllowedPersistenceIdentifier(string $persistenceIdentifier): bool + { + if (str_starts_with($persistenceIdentifier, 'NEW')) { + return true; + } + + if (!MathUtility::canBeInterpretedAsInteger($persistenceIdentifier)) { + return false; + } + + if (!$this->isAccessible()) { + return false; + } + + $uid = (int)$persistenceIdentifier; + $record = $this->repository->findByUid($uid); + + return $record !== null; + } + + /** + * @throws PersistenceManagerException + */ + private function extractUidFromIdentifier(FormIdentifier $identifier): int + { + if (!MathUtility::canBeInterpretedAsInteger($identifier->identifier)) { + throw new PersistenceManagerException( + sprintf('Invalid database identifier "%s". Expected numeric UID.', $identifier->identifier), + 1767199428 + ); + } + + return (int)$identifier->identifier; + } + + private function getStorageLocationLabel(): string + { + $languageService = $this->getLanguageService(); + return $languageService?->sL('LLL:EXT:form/Resources/Private/Language/Database.xlf:' . $this->getLabel()) ?: 'Database'; + } + + private function getLanguageService(): ?LanguageService + { + return $GLOBALS['LANG'] ?? null; + } +} diff --git a/Classes/Storage/ExtensionStorageAdapter.php b/Classes/Storage/ExtensionStorageAdapter.php new file mode 100644 index 0000000..1f92806 --- /dev/null +++ b/Classes/Storage/ExtensionStorageAdapter.php @@ -0,0 +1,354 @@ +ensureValidPersistenceIdentifier($identifier->identifier); + $file = $identifier->identifier; + $formDefinition = $this->yamlSource->load([$file]); + $this->generateErrorsIfFormDefinitionIsInvalidOrHasInvalidFileExtension($formDefinition, $identifier->identifier); + return FormData::fromArray($formDefinition); + } + + public function write(FormIdentifier $identifier, FormData $data, ?StorageContext $context = null): FormIdentifier + { + if (!$this->hasValidFileExtension($identifier->identifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be saved.', $identifier->identifier), 1764879569); + } + + if (!$this->storageConfiguration->isAllowedToSaveToExtensionPaths()) { + throw new PersistenceManagerException('Save to extension paths is not allowed.', 1764879520); + } + if (!$this->isFileWithinAccessibleExtensionFolders($identifier->identifier)) { + throw new PersistenceManagerException( + sprintf('The file "%s" could not be saved. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $identifier->identifier), + 1484073571 + ); + } + $fileToSave = GeneralUtility::getFileAbsFileName($identifier->identifier); + + try { + $this->yamlSource->save($fileToSave, $data->toArray()); + } catch (\Exception $e) { + throw new PersistenceManagerException( + sprintf('The file "%s" could not be saved: %s', $identifier->identifier, $e->getMessage()), + 1764879589, + $e + ); + } + return $identifier; + } + + public function delete(FormIdentifier $identifier): void + { + if (!$this->hasValidFileExtension($identifier->identifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $identifier->identifier), 1764879609); + } + if (!$this->exists($identifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $identifier->identifier), 1764879543); + } + if (!$this->storageConfiguration->isAllowedToDeleteFromExtensionPaths()) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $identifier->identifier), 1472239536); + } + if (!$this->isFileWithinAccessibleExtensionFolders($identifier->identifier)) { + $message = sprintf('The file "%s" could not be removed. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $identifier->identifier); + throw new PersistenceManagerException($message, 1484073878); + } + $fileToDelete = GeneralUtility::getFileAbsFileName($identifier->identifier); + unlink($fileToDelete); + } + + public function exists(FormIdentifier $identifier): bool + { + $exists = false; + if ($this->hasValidFileExtension($identifier->identifier)) { + if ($this->isFileWithinAccessibleExtensionFolders($identifier->identifier)) { + $exists = file_exists(GeneralUtility::getFileAbsFileName($identifier->identifier)); + } + } + return $exists; + } + + public function existsByFormIdentifier(string $formIdentifier): bool + { + foreach ($this->retrieveYamlFilesFromExtensionFolders() as $identifier) { + $formMetadata = $this->loadMetaData($identifier); + if ($this->looksLikeAFormDefinition($formMetadata) && $formMetadata->identifier === $formIdentifier) { + return true; + } + } + return false; + } + + public function findAll(SearchCriteria $criteria): array + { + $results = []; + foreach ($this->retrieveYamlFilesFromExtensionFolders() as $identifier) { + $formMetadata = $this->loadMetaData($identifier); + + if (!$this->looksLikeAFormDefinition($formMetadata)) { + continue; + } + + if (!$this->hasValidFileExtension($identifier)) { + continue; + } + + $readOnly = !$this->storageConfiguration->isAllowedToSaveToExtensionPaths(); + $formMetadata = $formMetadata->withReadOnly($readOnly); + + $removable = $this->storageConfiguration->isAllowedToDeleteFromExtensionPaths(); + $formMetadata = $formMetadata->withRemovable($removable); + + if (!$this->matchesCriteria($formMetadata, $criteria)) { + continue; + } + + $results[] = $formMetadata; + } + + return $results; + } + + /** + * Return a list of all accessible extension folders + * + * Only registered mount points from + * persistenceManager.allowedExtensionPaths + * are listed. + */ + public function getAccessibleExtensionFolders(): array + { + $cacheKey = 'ext-form-accessibleExtensionFolders'; + + if ($this->runtimeCache->has($cacheKey)) { + return $this->runtimeCache->get($cacheKey); + } + + $extensionFolders = []; + $allowedExtensionPaths = $this->storageConfiguration->getAllowedExtensionPaths(); + + if (empty($allowedExtensionPaths)) { + $this->runtimeCache->set($cacheKey, $extensionFolders); + return $extensionFolders; + } + + foreach ($allowedExtensionPaths as $allowedExtensionPath) { + if (!PathUtility::isExtensionPath($allowedExtensionPath)) { + continue; + } + $allowedExtensionFullPath = GeneralUtility::getFileAbsFileName($allowedExtensionPath); + if (!file_exists($allowedExtensionFullPath)) { + continue; + } + $allowedExtensionPath = rtrim($allowedExtensionPath, '/') . '/'; + $extensionFolders[$allowedExtensionPath] = $allowedExtensionFullPath; + } + + $this->runtimeCache->set($cacheKey, $extensionFolders); + return $extensionFolders; + } + + /** + * Retrieves yaml files from extension folders for further processing. + * At this time it's not determined yet, whether these files contain form data. + * + * @return string[] + */ + protected function retrieveYamlFilesFromExtensionFolders(): array + { + $filesFromExtensionFolders = []; + foreach ($this->getAccessibleExtensionFolders() as $relativePath => $fullPath) { + foreach (new \DirectoryIterator($fullPath) as $fileInfo) { + if ($fileInfo->getExtension() !== 'yaml') { + continue; + } + $filesFromExtensionFolders[] = $relativePath . $fileInfo->getFilename(); + } + } + return $filesFromExtensionFolders; + } + + protected function loadMetaData(string $fileOrIdentifier): FormMetadata + { + $this->ensureValidPersistenceIdentifier($fileOrIdentifier); + $persistenceIdentifier = $fileOrIdentifier; + $rawYamlContent = false; + $absoluteFilePath = GeneralUtility::getFileAbsFileName($fileOrIdentifier); + if ($absoluteFilePath !== '' && file_exists($absoluteFilePath)) { + $rawYamlContent = file_get_contents($absoluteFilePath); + } + + try { + if ($rawYamlContent === false) { + throw new NoSuchFileException(sprintf('YAML file "%s" could not be loaded', $persistenceIdentifier), 1524684462); + } + $yaml = $this->extractMetaDataFromCouldBeFormDefinition($rawYamlContent); + $this->generateErrorsIfFormDefinitionIsInvalidOrHasInvalidFileExtension($yaml, $persistenceIdentifier); + return FormMetadata::createFromYaml( + $yaml, + $persistenceIdentifier, + )->withStorageLocation($this->buildStorageLocationLabel($persistenceIdentifier)); + } catch (\Exception $e) { + return FormMetadata::createInvalid($persistenceIdentifier, $e->getMessage()); + } + } + + protected function isAccessibleExtensionFolder(string $folderName): bool + { + $folderName = rtrim($folderName, '/') . '/'; + return array_key_exists($folderName, $this->getAccessibleExtensionFolders()); + } + + protected function isFileWithinAccessibleExtensionFolders(string $fileName): bool + { + $pathInfo = PathUtility::pathinfo($fileName, PATHINFO_DIRNAME); + $dirName = rtrim($pathInfo, '/') . '/'; + return array_key_exists($dirName, $this->getAccessibleExtensionFolders()); + } + + /** + * @throws PersistenceManagerException + */ + protected function ensureValidPersistenceIdentifier(string $identifier): void + { + if (pathinfo($identifier, PATHINFO_EXTENSION) !== 'yaml') { + throw new PersistenceManagerException(sprintf('The file "%s" could not be loaded.', $identifier), 1764879628); + } + if (PathUtility::isExtensionPath($identifier) + && !$this->isFileWithinAccessibleExtensionFolders($identifier) + ) { + throw new PersistenceManagerException( + sprintf('The file "%s" could not be loaded. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $identifier), + 1484071985 + ); + } + } + + /** + * Check if a storage location (extension folder) is allowed + */ + public function isAllowedStorageLocation(string $storageLocation): bool + { + // For extension storage, storageLocation is a folder path within allowed extensions + return $this->isAccessibleExtensionFolder($storageLocation); + } + + /** + * Check if a persistence identifier (full file path) is allowed + */ + public function isAllowedPersistenceIdentifier(string $persistenceIdentifier): bool + { + // For extension storage, persistence identifier is a full file path (EXT:...) + return $this->hasValidFileExtension($persistenceIdentifier) + && $this->isFileWithinAccessibleExtensionFolders($persistenceIdentifier); + } + + public function getFormManagerOptions(): array + { + $preparedAccessibleFormStorageFolders = []; + if ($this->storageConfiguration->isAllowedToSaveToExtensionPaths()) { + foreach ($this->getAccessibleExtensionFolders() as $relativePath => $fullPath) { + $preparedAccessibleFormStorageFolders[] = [ + 'label' => $relativePath, + 'value' => $relativePath, + ]; + } + } + return [ + 'allowedStorageLocations' => $preparedAccessibleFormStorageFolders, + ]; + } + + public function isAccessible(): bool + { + return $this->storageConfiguration->isAllowedToSaveToExtensionPaths() && !empty($this->getAccessibleExtensionFolders()); + } + + /** + * Build a user-friendly storage location label + * Format: "extension_key/Configuration/Forms/file.form.yaml" + */ + protected function buildStorageLocationLabel(string $persistenceIdentifier): string + { + return $persistenceIdentifier; + } +} diff --git a/Classes/Storage/JsonObjectKeyOrderPreserver.php b/Classes/Storage/JsonObjectKeyOrderPreserver.php new file mode 100644 index 0000000..5bf0a2b --- /dev/null +++ b/Classes/Storage/JsonObjectKeyOrderPreserver.php @@ -0,0 +1,110 @@ + label) keyed by option value. json_encode() of such a map + * produces a JSON *object*, and MySQL's native JSON column type does not + * guarantee that a JSON object's member order survives a write/read round + * trip. This is documented, spec-compliant behavior (RFC 8259: object + * member order "has no significance"). JSON *array* element order, by + * contrast, is reliably preserved by MySQL. + * + * MariaDB's JSON type is a plain LONGTEXT alias with a + * CHECK(JSON_VALID(...)) constraint, so it happens to preserve the exact + * text (and therefore object member order) byte-for-byte, which is why + * this only reproduces on real MySQL. + * + * Practical effect without this workaround: reordering a select element's + * options in the form editor visibly "works" right after saving, but + * reverts to the previous order on the next reload, once MySQL has + * renormalized the JSON object. + * + * protect() wraps every "options" map in an array-based structure before + * persisting, so the intended order survives via a JSON array instead of + * relying on object member order. restore() reverses this again after + * json_decode() on read, using the explicit order list rather than the + * member order MySQL happened to return the object in. + * + * Note: "options" is matched by key name rather than by resolving each + * renderable's prototype configuration for declared multi-value + * properties (as FormEditorController does for the editor UI). This is a + * deliberate simplification. It also protects option order inside + * variant overrides for free, without needing prototype/DI wiring in the + * persistence layer and is safe even where it over-applies, since + * protect()/restore() are lossless no-ops on any "options" map that + * doesn't need reordering. + * + * @internal + */ +final readonly class JsonObjectKeyOrderPreserver +{ + private const string MARKER = '__jsonKeyOrderProtected'; + + public function protect(array $formDefinition): array + { + $output = $formDefinition; + foreach ($formDefinition as $key => $value) { + if (!is_array($value)) { + continue; + } + if ($key === 'options' && !array_is_list($value)) { + $output[$key] = [ + self::MARKER => true, + 'order' => array_keys($value), + 'values' => $value, + ]; + continue; + } + $output[$key] = $this->protect($value); + } + return $output; + } + + public function restore(array $formDefinition): array + { + $output = $formDefinition; + foreach ($formDefinition as $key => $value) { + if (!is_array($value)) { + continue; + } + if ($key === 'options' && ($value[self::MARKER] ?? false) === true) { + $order = $value['order'] ?? []; + $values = $value['values'] ?? []; + $restored = []; + foreach ($order as $optionKey) { + if (array_key_exists($optionKey, $values)) { + $restored[$optionKey] = $values[$optionKey]; + unset($values[$optionKey]); + } + } + // Defensive fallback for entries the order list doesn't cover + // (should not normally happen, keeps old/foreign data intact). + $output[$key] = $restored + $values; + continue; + } + $output[$key] = $this->restore($value); + } + return $output; + } +} diff --git a/Classes/Storage/Permission/DatabasePermissionChecker.php b/Classes/Storage/Permission/DatabasePermissionChecker.php new file mode 100644 index 0000000..6680c1e --- /dev/null +++ b/Classes/Storage/Permission/DatabasePermissionChecker.php @@ -0,0 +1,152 @@ +hasBackendUser()) { + return false; + } + return $this->tcaSchemaFactory->has(FormDefinitionRepository::TABLE_NAME) + && $this->hasTableReadAccess() + && $this->hasPageAccess($pageId); + } + + /** + * Assert that the current backend user has read permissions for the page + * a given form record is stored on. + * + * @throws PersistenceManagerException + */ + public function assertReadAccessForRecord(int $uid, ?array $record): void + { + $pid = (int)($record['pid'] ?? throw new PersistenceManagerException( + sprintf('The form with uid "%d" has no valid pid.', $uid), + 1774364028 + )); + + if (!$this->hasReadPermission($pid)) { + throw new PersistenceManagerException( + sprintf('Access denied: You do not have permission to access forms on page "%d".', $pid), + 1774364031 + ); + } + } + + /** + * Check if the current backend user has write permissions for the given page + */ + public function hasWritePermission(int $pageId): bool + { + if (!$this->hasBackendUser()) { + return false; + } + return $this->tcaSchemaFactory->has(FormDefinitionRepository::TABLE_NAME) + && $this->hasTableWriteAccess() + && $this->hasPageAccess($pageId); + } + + /** + * Assert that the current backend user has write permissions for the page + * a given form record is stored on. + * + * @throws PersistenceManagerException + */ + public function assertWriteAccessForRecord(int $uid, ?array $record): void + { + $pid = (int)($record['pid'] ?? throw new PersistenceManagerException( + sprintf('The form with uid "%d" has no valid pid.', $uid), + 1767199436 + )); + + if (!$this->hasWritePermission($pid)) { + throw new PersistenceManagerException( + sprintf('Access denied: You do not have permission to persist forms on page "%d".', $pid), + 1767199442 + ); + } + } + + private function hasPageAccess(int $pageId): bool + { + $backendUser = $this->getBackendUser(); + if ($backendUser->isAdmin()) { + return true; + } + if ($pageId <= 0) { + return true; + } + + $pageRow = BackendUtility::getRecord('pages', $pageId); + if ($pageRow === null) { + return false; + } + + // For all other pages, check web mount and page permissions + if ($backendUser->isInWebMount($pageId) === null) { + return false; + } + return $backendUser->doesUserHaveAccess($pageRow, Permission::PAGE_SHOW); + } + + private function hasTableReadAccess(): bool + { + return $this->getBackendUser()->check('tables_select', FormDefinitionRepository::TABLE_NAME); + } + + private function hasTableWriteAccess(): bool + { + return $this->getBackendUser()->check('tables_modify', FormDefinitionRepository::TABLE_NAME); + } + + private function hasBackendUser(): bool + { + return ($GLOBALS['BE_USER'] ?? null) instanceof BackendUserAuthentication; + } + + private function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } +} diff --git a/Classes/Storage/Security/FormDefinitionPersistenceCommand.php b/Classes/Storage/Security/FormDefinitionPersistenceCommand.php new file mode 100644 index 0000000..682a516 --- /dev/null +++ b/Classes/Storage/Security/FormDefinitionPersistenceCommand.php @@ -0,0 +1,31 @@ +findInvocationIndex($command, $identifier) !== null) { + return false; + } + $item = [ + 'command' => $command, + 'identifier' => $identifier, + ]; + if ($fields !== null) { + $processed = $this->processFields($fields); + $item['names'] = $processed['names']; + $item['hmac'] = $processed['hmac']; + } + $this->allowedInvocations[] = $item; + return true; + } + + /** + * Returns true if a matching invocation has been granted and not yet consumed. + * The provided fields must produce the same sorted key list and HMAC as + * the fields that were registered via allowInvocation(). + */ + public function isInvocationAllowed( + FormDefinitionPersistenceCommand $command, + string|int $identifier, + ?array $fields = null, + ): bool { + $index = $this->findInvocationIndex($command, $identifier); + if ($index === null) { + return false; + } + if ($fields === null) { + return true; + } + $item = $this->allowedInvocations[$index]; + $processed = $this->processFields($fields); + return $item['names'] === $processed['names'] && $item['hmac'] === $processed['hmac']; + } + + /** + * Consumes a matching invocation (removes it from the pending list). + * Called both by the hook after successful verification (single-use + * enforcement) and by the repository's finally block (cleanup). + */ + public function consumeInvocation( + FormDefinitionPersistenceCommand $command, + string|int $identifier, + ?array $fields = null, + ): void { + $index = $this->findInvocationIndex($command, $identifier); + if ($index === null) { + return; + } + if ($fields === null) { + unset($this->allowedInvocations[$index]); + return; + } + $item = $this->allowedInvocations[$index]; + $processed = $this->processFields($fields); + if ($item['names'] === $processed['names'] && $item['hmac'] === $processed['hmac']) { + unset($this->allowedInvocations[$index]); + } + } + + private function findInvocationIndex(FormDefinitionPersistenceCommand $command, string|int $identifier): ?int + { + foreach ($this->allowedInvocations as $index => $invocation) { + if ($invocation['command'] === $command && $invocation['identifier'] === $identifier) { + return $index; + } + } + return null; + } + + /** + * Sorts fields alphabetically and returns an array with keys 'names' and 'hmac'. + * + * @return array{names: list, hmac: string} + */ + private function processFields(array $fields): array + { + ksort($fields); + return [ + 'names' => array_keys($fields), + 'hmac' => $this->hashService->hmac( + json_encode($fields, JSON_THROW_ON_ERROR), + FormDefinitionPersistenceGuard::class, + HashAlgo::SHA3_384 + ), + ]; + } +} diff --git a/Classes/Storage/StorageAdapterFactory.php b/Classes/Storage/StorageAdapterFactory.php new file mode 100644 index 0000000..24403ee --- /dev/null +++ b/Classes/Storage/StorageAdapterFactory.php @@ -0,0 +1,151 @@ + + */ + private array $adapters; + + /** + * @param iterable $adapters + */ + public function __construct(iterable $adapters) + { + $this->adapters = $this->sortAdaptersByPriority($adapters); + } + + /** + * Get storage adapter that can handle the given persistence identifier + * + * Uses Chain of Responsibility pattern to find the first adapter + * (in priority order) that supports the given identifier. + * + * @param string $identifier Persistence identifier (e.g., "EXT:my_extension/Forms/contact.form.yaml", "1:/forms/contact.form.yaml") + * @throws \RuntimeException if no adapter can handle the identifier + */ + public function getAdapterForIdentifier(string $identifier): StorageAdapterInterface + { + foreach ($this->adapters as $adapter) { + if ($adapter->supports($identifier)) { + return $adapter; + } + } + + throw new \RuntimeException( + sprintf( + 'No storage adapter found that can handle identifier "%s". Registered adapters: %s', + $identifier, + implode(', ', array_map(fn($a) => $a->getTypeIdentifier(), $this->adapters)) + ), + 1731672000 + ); + } + + /** + * Get adapter by type identifier + * + * @param string $typeIdentifier Type identifier (e.g., 'extension', 'filemount') + * @throws \InvalidArgumentException if no adapter with this type identifier exists + */ + public function getAdapterByType(string $typeIdentifier): StorageAdapterInterface + { + foreach ($this->adapters as $adapter) { + if ($adapter->getTypeIdentifier() === $typeIdentifier) { + return $adapter; + } + } + + throw new \InvalidArgumentException( + sprintf( + 'No storage adapter found with type identifier "%s". Available types: %s', + $typeIdentifier, + implode(', ', array_map(fn($a) => $a->getTypeIdentifier(), $this->adapters)) + ), + 1731672002 + ); + } + + /** + * Check if an adapter with the given type identifier exists + */ + public function hasAdapterType(string $typeIdentifier): bool + { + foreach ($this->adapters as $adapter) { + if ($adapter->getTypeIdentifier() === $typeIdentifier) { + return true; + } + } + return false; + } + + /** + * Get all registered storage adapters + * + * @return list + */ + public function getAllAdapters(): array + { + return $this->adapters; + } + + /** + * Get all registered storage type identifiers + * + * @return list + */ + public function getRegisteredTypeIdentifiers(): array + { + return array_map( + fn(StorageAdapterInterface $adapter) => $adapter->getTypeIdentifier(), + $this->adapters + ); + } + + /** + * Sort adapters by priority (highest first) + * + * @param iterable $adapters + * @return list + */ + private function sortAdaptersByPriority(iterable $adapters): array + { + $sortedAdapters = [...$adapters]; + + usort( + $sortedAdapters, + fn(StorageAdapterInterface $a, StorageAdapterInterface $b) => $b->getPriority() <=> $a->getPriority() + ); + + return $sortedAdapters; + } +} diff --git a/Classes/Storage/StorageAdapterInterface.php b/Classes/Storage/StorageAdapterInterface.php new file mode 100644 index 0000000..2f718ef --- /dev/null +++ b/Classes/Storage/StorageAdapterInterface.php @@ -0,0 +1,186 @@ + + */ + public function findAll(SearchCriteria $criteria): array; + + /** + * Get unique persistence identifier for a new form in this storage + * + * @param string $formIdentifier The form identifier (e.g., "contact-form") + * @param string $storageLocation The save path (e.g., "1:/forms/" for filemount, pid for database) + * @return string Unique persistence identifier + * @throws NoUniquePersistenceIdentifierException + */ + public function getUniquePersistenceIdentifier(string $formIdentifier, string $storageLocation): string; + + /** + * Check if a storage location is allowed for this adapter + * + * For database storage: storageLocation is a PID + * For file storage: storageLocation is a folder path (e.g., "1:/forms/") + * + * @param string $storageLocation The storage location to check + * @return bool True if the storage location is allowed + */ + public function isAllowedStorageLocation(string $storageLocation): bool; + + /** + * Check if a persistence identifier is allowed for this adapter + * + * For database storage: identifier is a UID or NEW* + * For file storage: identifier is a full file path (e.g., "1:/forms/contact.form.yaml") + * + * @param string $persistenceIdentifier The persistence identifier to check + * @return bool True if the persistence identifier is allowed + */ + public function isAllowedPersistenceIdentifier(string $persistenceIdentifier): bool; +} diff --git a/Classes/Type/FormDefinitionArray.php b/Classes/Type/FormDefinitionArray.php new file mode 100644 index 0000000..93f23f1 --- /dev/null +++ b/Classes/Type/FormDefinitionArray.php @@ -0,0 +1,24 @@ +getFileBasedForms(); + $count = count($forms); + + if ($count === 0) { + return 'No file-based form definitions found.'; + } + + $description = sprintf( + 'Found %d file-based form definition(s) that will be migrated to database storage:', + $count + ); + + foreach ($forms as $form) { + $description .= LF . sprintf( + ' • %s (%s)', + $form->name, + $form->persistenceIdentifier ?? $form->identifier + ); + } + + $description .= LF . LF . 'After migration, all tt_content references will be updated automatically.'; + $description .= LF . LF . 'Note: Only references in tt_content (CType form_formframework) are updated ' + . 'automatically. If your installation uses form persistence identifiers in custom ' + . 'database tables or FlexForm fields outside tt_content, these references must be ' + . 'updated manually.'; + $description .= LF . LF . 'The original YAML files WILL BE DELETED after successful migration. ' + . 'Please ensure backups exist. Failures will be logged and can be found in their ' + . 'configured log locations after execution, and should be reviewed.'; + + return $description; + } + + public function getConfirmation(): Confirmation + { + return new Confirmation( + 'Migrate forms to database?', + 'This will move all filemount-based form definitions into the database ' + . 'and update content element references in tt_content. ' + . 'References in custom database tables or FlexForm fields outside tt_content ' + . 'are NOT updated automatically and must be migrated manually. ' + . 'The original YAML files will be deleted after successful migration. ' + . 'YAML files in extension directories are not affected. ' + . 'Please make sure you have a backup before proceeding.', + false, + 'Yes, migrate forms to database', + 'No, keep file-based storage' + ); + } + + public function updateNecessary(): bool + { + return $this->getFileBasedForms() !== []; + } + + public function executeUpdate(): bool + { + $forms = $this->getFileBasedForms(); + + if ($forms === []) { + return true; + } + + $success = true; + $migrationMap = []; + $migratedFiles = []; + + foreach ($forms as $form) { + $persistenceIdentifier = $form->persistenceIdentifier ?? $form->identifier; + + try { + $formData = $this->readForm($persistenceIdentifier); + } catch (\Exception $e) { + $this->logger->error('Failed to load form definition from "{identifier}": {message}', [ + 'identifier' => $persistenceIdentifier, + 'message' => $e->getMessage(), + ]); + $success = false; + continue; + } + + // Check if this form was already migrated (by identifier) + $existingUid = $this->formDefinitionRepository->findUidByFormIdentifier($formData->identifier); + if ($existingUid !== null) { + $this->logger->info('Form "{identifier}" already exists in database, skipping.', [ + 'identifier' => $formData->identifier, + ]); + // Still track mapping for reference updates + $migrationMap[$persistenceIdentifier] = $existingUid; + $migratedFiles[] = $persistenceIdentifier; + continue; + } + + // Write to database using raw insert (no DataHandler required, + // so this works in Install Tool context without a backend user) + try { + $newUid = $this->formDefinitionRepository->addRaw(0, $formData); + } catch (\Exception $e) { + $this->logger->error('Database insert failed for form "{identifier}": {message}', [ + 'identifier' => $formData->identifier, + 'message' => $e->getMessage(), + ]); + $newUid = null; + } + + if ($newUid === null) { + $this->logger->error('Failed to insert form "{identifier}" into database.', [ + 'identifier' => $formData->identifier, + 'persistenceIdentifier' => $persistenceIdentifier, + ]); + $success = false; + continue; + } + + $migrationMap[$persistenceIdentifier] = $newUid; + $migratedFiles[] = $persistenceIdentifier; + + $this->logger->info('Migrated form "{identifier}" from "{file}" to database UID {uid}.', [ + 'identifier' => $formData->identifier, + 'file' => $persistenceIdentifier, + 'uid' => $newUid, + ]); + } + + // Update tt_content FlexForm references + if ($migrationMap !== []) { + // Convert int UIDs to string for the service (persistenceIdentifier values are always strings) + $stringMap = array_map(strval(...), $migrationMap); + $referencesUpdated = $this->formTransferService->updateContentElementReferences($stringMap); + $this->logger->info('Updated {count} content element reference(s).', [ + 'count' => $referencesUpdated, + ]); + } + + // Delete original YAML files only when all forms were migrated successfully. + // If any migration failed, keep all files to allow re-running the wizard. + if ($success && $migratedFiles !== []) { + $deletedCount = $this->deleteOriginalFiles($migratedFiles); + $this->logger->info('Deleted {count} of {total} original YAML file(s).', [ + 'count' => $deletedCount, + 'total' => count($migratedFiles), + ]); + } elseif (!$success && $migratedFiles !== []) { + $this->logger->warning( + 'Some forms could not be migrated. Original YAML files were kept to allow re-running the wizard.' + ); + } + + return $success; + } + + public function getPrerequisites(): array + { + return [ + DatabaseUpdatedPrerequisite::class, + ]; + } + + /** + * Find all YAML form definitions in configured file mounts. + * + * @return list + */ + private function getFileBasedForms(): array + { + try { + $results = []; + foreach ($this->retrieveYamlFilesFromStorageFolders() as $file) { + $formMetadata = $this->loadMetaData($file); + + if (!$this->looksLikeAFormDefinition($formMetadata)) { + continue; + } + + if (!$this->hasValidFileExtension($file->getCombinedIdentifier())) { + continue; + } + $results[] = $formMetadata; + } + return $results; + } catch (\Exception $e) { + $this->logger->warning('Could not list file-based forms: {message}', [ + 'message' => $e->getMessage(), + ]); + return []; + } + } + + /** + * Delete original YAML files from file storage after successful migration. + * + * Files that cannot be deleted (e.g. due to permissions) are logged but + * do not cause the overall migration to fail — the database records are + * already the authoritative source at this point. + * + * @param list $persistenceIdentifiers Combined identifiers (e.g. "1:/form_definitions/contact.form.yaml") + * @return int Number of successfully deleted files + */ + private function deleteOriginalFiles(array $persistenceIdentifiers): int + { + $deletedCount = 0; + + foreach ($persistenceIdentifiers as $persistenceIdentifier) { + try { + $this->deleteForm($persistenceIdentifier); + $deletedCount++; + + $this->logger->info('Deleted original YAML file "{identifier}".', [ + 'identifier' => $persistenceIdentifier, + ]); + } catch (\Exception $e) { + $this->logger->warning('Could not delete original YAML file "{identifier}": {message}', [ + 'identifier' => $persistenceIdentifier, + 'message' => $e->getMessage(), + ]); + } + } + + return $deletedCount; + } + + private function readForm(string $identifier): FormData + { + $file = $this->retrieveFileByPersistenceIdentifier($identifier); + $formDefinition = $this->yamlSource->load([$file]); + $this->generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension($formDefinition, $identifier); + return FormData::fromArray($formDefinition); + } + + private function deleteForm(string $identifier): void + { + if (!$this->hasValidFileExtension($identifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $identifier), 1472239534); + } + if (!$this->exists($identifier)) { + throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $identifier), 1764879545); + } + [$storageUid, $fileIdentifier] = explode(':', $identifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $file = $storage->getFile($fileIdentifier); + if (!$storage->checkFileActionPermission('delete', $file)) { + throw new PersistenceManagerException(sprintf('No delete access to file "%s".', $identifier), 1472239516); + } + $storage->deleteFile($file); + } + + /** + * @throws PersistenceManagerException + * @throws NoSuchFileException + */ + private function retrieveFileByPersistenceIdentifier(string $identifier): File + { + $this->ensureValidPersistenceIdentifier($identifier); + try { + $file = $this->resourceFactory->retrieveFileOrFolderObject($identifier); + } catch (\Exception) { + // Top level catch to ensure useful following exception handling, because FAL throws top level exceptions. + $file = null; + } + if ($file === null) { + throw new NoSuchFileException(sprintf('YAML file "%s" could not be loaded', $identifier), 1524684442); + } + if (!$file->getStorage()->checkFileActionPermission('read', $file)) { + throw new PersistenceManagerException(sprintf('No read access to file "%s".', $identifier), 1471630578); + } + return $file; + } + + /** + * @throws PersistenceManagerException + */ + private function ensureValidPersistenceIdentifier(string $identifier): void + { + if (pathinfo($identifier, PATHINFO_EXTENSION) !== 'yaml') { + throw new PersistenceManagerException(sprintf('The file "%s" could not be loaded.', $identifier), 1477679819); + } + } + + /** + * @throws PersistenceManagerException + */ + private function generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension(array $formDefinition, string $identifier): void + { + if ($this->looksLikeAFormDefinitionArray($formDefinition) && !$this->hasValidFileExtension($identifier)) { + throw new PersistenceManagerException(sprintf('Form definition "%s" does not end with ".form.yaml".', $identifier), 1780660703); + } + } + + /** + * Check if array looks like a form definition + */ + private function looksLikeAFormDefinitionArray(array $data): bool + { + return !empty($data['identifier']) && trim($data['type'] ?? '') === 'Form'; + } + + private function hasValidFileExtension(string $identifier): bool + { + return str_ends_with($identifier, FormPersistenceManagerInterface::FORM_DEFINITION_FILE_EXTENSION); + } + + private function exists(string $identifier): bool + { + $exists = false; + if ($this->hasValidFileExtension($identifier) && $this->pathIsIntendedAsFileMountPath($identifier)) { + [$storageUid, $fileIdentifier] = explode(':', $identifier, 2); + $storage = $this->getStorageByUid((int)$storageUid); + $exists = $storage->hasFile($fileIdentifier); + } + return $exists; + } + + /** + * Returns a ResourceStorage for a given uid + * + * @throws PersistenceManagerException + */ + private function getStorageByUid(int $storageUid): ResourceStorage + { + $storage = $this->storageRepository->findByUid($storageUid); + if (!$storage?->isBrowsable()) { + throw new PersistenceManagerException(sprintf('Could not access storage with uid "%d".', $storageUid), 1471630581); + } + return $storage; + } + + private function pathIsIntendedAsFileMountPath(string $path): bool + { + if (empty($path)) { + return false; + } + [$storageUid, $pathIdentifier] = explode(':', $path, 2); + if (empty($storageUid) || empty($pathIdentifier)) { + return false; + } + return MathUtility::canBeInterpretedAsInteger($storageUid); + } + + /** + * Retrieves yaml files from storage folders for further processing. + * At this time it's not determined yet, whether these files contain form data. + * + * @return File[] + */ + private function retrieveYamlFilesFromStorageFolders(): array + { + $filesFromStorageFolders = []; + $fileExtensionFilter = GeneralUtility::makeInstance(FileExtensionFilter::class); + $fileExtensionFilter->setAllowedFileExtensions(['yaml']); + foreach ($this->getAccessibleFormStorageFolders() as $folder) { + $storage = $folder->getStorage(); + $storage->setFileAndFolderNameFilters([ + [$fileExtensionFilter, 'filterFileList'], + ]); + $files = $folder->getFiles(0, 0, Folder::FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS, true); + array_push($filesFromStorageFolders, ...array_values($files)); + $storage->resetFileAndFolderNameFiltersToDefault(); + } + return $filesFromStorageFolders; + } + + /** + * Return a list of all accessible file mountpoints for the + * current backend user. + * + * Only registered mount points from + * persistenceManager.allowedFileMounts + * are listed. + * + * @return Folder[] + */ + private function getAccessibleFormStorageFolders(): array + { + $storageFolders = []; + $allowedFileMounts = $this->storageConfiguration->getPersistenceManagerConfiguration()->allowedFileMounts; + + if (empty($allowedFileMounts)) { + return $storageFolders; + } + + foreach ($allowedFileMounts as $allowedFileMount) { + $allowedFileMount = rtrim($allowedFileMount, '/') . '/'; + [$storageUid, $fileMountPath] = explode(':', $allowedFileMount, 2); + try { + $storage = $this->getStorageByUid((int)$storageUid); + } catch (PersistenceManagerException) { + continue; + } + $isStorageFileMount = false; + $parentFolder = $storage->getRootLevelFolder(false); + foreach ($storage->getFileMounts() as $storageFileMount) { + $storageFileMountFolder = $storageFileMount['folder']; + // Normally should use ResourceStorage::isWithinFolder() to check if the configured file mount path is within + // a storage file mount but this requires a valid Folder object and thus a directory which already exists. + // And the folder could simply not exist yet. + if (str_starts_with($fileMountPath, $storageFileMountFolder->getIdentifier())) { + $isStorageFileMount = true; + $parentFolder = $storageFileMountFolder; + } + } + // Get storage folder object, create it if missing + try { + $fileMountFolder = $storage->getFolder($fileMountPath); + } catch (InsufficientFolderAccessPermissionsException) { + continue; + } catch (FolderDoesNotExistException) { + if ($isStorageFileMount) { + $fileMountPath = substr( + $fileMountPath, + strlen($parentFolder->getIdentifier()) + ); + } + try { + $fileMountFolder = $storage->createFolder($fileMountPath, $parentFolder); + } catch (InsufficientFolderAccessPermissionsException) { + continue; + } + } + $storageFolders[$allowedFileMount] = $fileMountFolder; + } + return $storageFolders; + } + + private function loadMetaData(File $file): FormMetadata + { + $persistenceIdentifier = $file->getCombinedIdentifier(); + $rawYamlContent = $file->getContents(); + + try { + $yaml = $this->extractMetaDataFromCouldBeFormDefinition($rawYamlContent); + $this->generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension($yaml, $persistenceIdentifier); + return FormMetadata::createFromYaml( + $yaml, + $persistenceIdentifier, + $file->getUid() + ); + } catch (\Exception $e) { + return FormMetadata::createInvalid($persistenceIdentifier, $e->getMessage()); + } + } + + private function extractMetaDataFromCouldBeFormDefinition(string $maybeRawFormDefinition): array + { + $metaDataProperties = ['identifier', 'type', 'label', 'prototypeName']; + $metaData = []; + foreach (explode(LF, $maybeRawFormDefinition) as $line) { + if (empty($line) || $line[0] === ' ') { + continue; + } + $parts = explode(':', $line, 2); + $key = trim($parts[0]); + if (!($parts[1] ?? null) || !in_array($key, $metaDataProperties, true)) { + continue; + } + if ($key === 'label') { + try { + $parsedLabelLine = Yaml::parse($line); + $value = $parsedLabelLine['label'] ?? ''; + } catch (ParseException) { + $value = ''; + } + } else { + $value = trim($parts[1], " '\"\r"); + } + $metaData[$key] = $value; + } + return $metaData; + } + + private function looksLikeAFormDefinition(FormMetadata $formMetadata): bool + { + return !empty($formMetadata->identifier) && trim($formMetadata->type) === 'Form'; + } + +} diff --git a/Classes/Utility/DateRangeValidatorPatterns.php b/Classes/Utility/DateRangeValidatorPatterns.php new file mode 100644 index 0000000..998acf4 --- /dev/null +++ b/Classes/Utility/DateRangeValidatorPatterns.php @@ -0,0 +1,66 @@ +registerArgument('contentElementUid', 'int', 'The uid of a content element'); + $this->registerArgument('formPersistenceIdentifier', 'string', 'The form persistence identifier for return URL', false, ''); + } + + public function render(): string + { + $content = ''; + $contentElementUid = $this->arguments['contentElementUid']; + $contentRecord = BackendUtility::getRecord('tt_content', $contentElementUid); + $request = null; + if ($this->renderingContext->hasAttribute(ServerRequestInterface::class)) { + $request = $this->renderingContext->getAttribute(ServerRequestInterface::class); + } + if (!empty($contentRecord) && $request !== null) { + $backendLayout = GeneralUtility::makeInstance(BackendLayout::class, 'dummy', 'dummy', []); + $pageId = (int)$contentRecord['pid']; + $pageContext = $request->getAttribute('pageContext'); + if (!$pageContext instanceof PageContext) { + try { + $pageContext = $this->pageContextFactory->createFromRequest($request, $pageId, $this->getBackendUser()); + } catch (\Exception $e) { + return ''; + } + } + + $manipulatedRequest = $this->getManipulatedRequestToFormEditor($request, $contentRecord); + + $pageLayoutContext = GeneralUtility::makeInstance( + PageLayoutContext::class, + $pageContext, + $backendLayout, + DrawingConfiguration::create($backendLayout, BackendUtility::getPagesTSconfig($pageId), PageViewMode::LayoutView), + $manipulatedRequest + ); + $gridColumn = GeneralUtility::makeInstance(GridColumn::class, $pageLayoutContext, []); + $contentRecord = $this->recordFactory->createResolvedRecordFromDatabaseRow('tt_content', $contentRecord, null, $pageLayoutContext->getRecordIdentityMap()); + $columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $pageLayoutContext, $gridColumn, $contentRecord); + return $columnItem->getPreview(); + } + return $content; + } + + private function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * Create a manipulated request with custom NormalizedParams to override the return URL. + * This allows customizing the return URL used by PageLayoutContext->getReturnUrl() + * without modifying the original request or the PageLayoutContext logic. + */ + private function getManipulatedRequestToFormEditor(ServerRequestInterface $request, array $contentRecord): ServerRequestInterface + { + $serverParams = $request->getServerParams(); + $serverParams['REQUEST_URI'] = $this->buildCustomReturnUrl($request, $contentRecord); + + $customNormalizedParams = NormalizedParams::createFromServerParams($serverParams); + + return $request->withAttribute('normalizedParams', $customNormalizedParams); + } + + /** + * Build the custom return URL for the form editor. + * Generates the URL to FormEditor->index action with the formPersistenceIdentifier parameter. + */ + private function buildCustomReturnUrl(ServerRequestInterface $request, array $contentRecord): string + { + $formPersistenceIdentifier = $this->arguments['formPersistenceIdentifier'] ?? ''; + + if (empty($formPersistenceIdentifier)) { + return $request->getAttribute('normalizedParams')->getRequestUri(); + } + + $uri = $this->uriBuilder->buildUriFromRoute( + 'form_editor', + ['formPersistenceIdentifier' => $formPersistenceIdentifier] + ); + return (string)$uri; + } +} diff --git a/Classes/ViewHelpers/Form/UploadDeleteCheckboxViewHelper.php b/Classes/ViewHelpers/Form/UploadDeleteCheckboxViewHelper.php new file mode 100644 index 0000000..19679b6 --- /dev/null +++ b/Classes/ViewHelpers/Form/UploadDeleteCheckboxViewHelper.php @@ -0,0 +1,117 @@ + + * ``` + * + * Scope: frontend + * + * @see https://docs.typo3.org/permalink/t3viewhelper:typo3-form-form-uploaddeletecheckbox + */ +final class UploadDeleteCheckboxViewHelper extends AbstractFormFieldViewHelper +{ + /** + * @var string + */ + protected $tagName = 'input'; + + public function __construct( + private readonly HashService $hashService, + ) { + parent::__construct(); + } + + public function initializeArguments(): void + { + parent::initializeArguments(); + $this->registerArgument('fileReference', FileReference::class, 'The file reference object', true); + $this->registerArgument('fileIndex', 'int', 'Index of the file in multiple upload context', false, 0); + } + + public function render(): string + { + /** @var FileReference|null $fileReference */ + $fileReference = $this->arguments['fileReference']; + $fileIndex = (int)$this->arguments['fileIndex']; + + // Early return if no file reference given + if (!$fileReference instanceof FileReference) { + return ''; + } + + $this->tag->addAttribute('type', 'checkbox'); + + // Build the deletion data that will be validated on submit + $deleteData = [ + 'property' => $this->arguments['property'], + 'fileIndex' => $fileIndex, + 'fileUid' => $fileReference->getUid() ?? $fileReference->getOriginalResource()->getOriginalFile()->getUid(), + ]; + + // Create HMAC-signed value + $valueAttribute = $this->hashService->appendHmac( + json_encode($deleteData, JSON_THROW_ON_ERROR), + HashScope::DeleteFile->prefix() + ); + + // Build name attribute using the form field prefix + $name = $this->getName(); + $nameAttribute = $name . '[__deleteFile][' . $fileIndex . ']'; + + $this->tag->addAttribute('name', $nameAttribute); + $this->tag->addAttribute('value', $valueAttribute); + + // Check if this checkbox was previously checked (in case of validation errors) + if ($this->isChecked($fileIndex)) { + $this->tag->addAttribute('checked', 'checked'); + } + + return $this->tag->render(); + } + + /** + * Checks if the checkbox for the given file index was checked in the current request + */ + private function isChecked(int $fileIndex): bool + { + $value = $this->getValueAttribute(); + if (is_array($value) && isset($value['__deleteFile'][$fileIndex])) { + return !empty($value['__deleteFile'][$fileIndex]); + } + return false; + } +} diff --git a/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php b/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php new file mode 100644 index 0000000..c7e92fd --- /dev/null +++ b/Classes/ViewHelpers/Form/UploadedResourceViewHelper.php @@ -0,0 +1,162 @@ +registerArgument('as', 'string', ''); + $this->registerArgument('accept', 'array', 'Values for the accept attribute', false, []); + $this->registerArgument('errorClass', 'string', 'CSS class to set if there are errors for this ViewHelper', false, 'f3-form-error'); + $this->registerArgument('multiple', 'boolean', 'Defines the upload element accepting multiple files', false, false); + } + + public function render(): string + { + $output = ''; + + $name = $this->getName(); + $as = $this->arguments['as']; + $accept = $this->arguments['accept']; + $multiple = $this->arguments['multiple']; + $resource = $this->getUploadedResource(); + + if (!empty($accept)) { + $this->tag->addAttribute('accept', implode(',', $accept)); + } + + if ($resource !== null) { + if ($resource instanceof FileReference) { + $resourcePointerValue = $resource->getUid() ?? ('file:' . $resource->getOriginalResource()->getOriginalFile()->getUid()); + $output .= $this->buildResourcePointerInput( + 0, + (string)$resourcePointerValue, + $this->buildResourcePointerIdAttribute(), + ); + } elseif ($resource instanceof ObjectStorage) { + foreach ($resource as $file) { + $index = $resource->getPosition($file); + $resourcePointerValue = $file->getUid() ?? ('file:' . $file->getOriginalResource()->getOriginalFile()->getUid()); + $output .= $this->buildResourcePointerInput( + $index, + (string)$resourcePointerValue, + $this->buildResourcePointerIdAttribute('-' . $index), + ); + } + } + + $this->templateVariableContainer->add($as, $resource); + $output .= $this->renderChildren(); + $this->templateVariableContainer->remove($as); + } + + foreach (['name', 'type', 'tmp_name', 'error', 'size'] as $fieldName) { + $this->registerFieldNameForFormTokenGeneration($name . '[' . $fieldName . ']'); + } + $this->tag->addAttribute('type', 'file'); + + if ($multiple === true) { + $this->tag->addAttribute('name', $name . '[]'); + $this->tag->addAttribute('multiple', true); + } else { + $this->tag->addAttribute('name', $name); + } + + $this->setErrorClassAttribute(); + $output .= $this->tag->render(); + + return $output; + } + + private function buildResourcePointerInput(int $index, string $resourcePointerValue, string $idAttribute): string + { + $name = htmlspecialchars($this->getName()); + $hmac = htmlspecialchars($this->hashService->appendHmac($resourcePointerValue, HashScope::ResourcePointer->prefix())); + return ''; + } + + private function buildResourcePointerIdAttribute(string $suffix = ''): string + { + if (!isset($this->additionalArguments['id'])) { + return ''; + } + return ' id="' . htmlspecialchars($this->additionalArguments['id']) . '-file-reference' . $suffix . '"'; + } + + /** + * Return a previously uploaded resource. + * Return NULL if errors occurred during property mapping for this property. + */ + private function getUploadedResource(): FileReference|ObjectStorage|null + { + if ($this->getMappingResultsForProperty()->hasErrors()) { + return null; + } + $resource = $this->getValueAttribute(); + if ($resource instanceof ObjectStorage) { + return $resource; + } + if ($resource instanceof FileReference) { + // When multiple uploads are enabled but the stored value is a single + // FileReference, wrap it in an ObjectStorage so that the Fluid template's + // f:for ViewHelper receives an iterable instead of crashing. + if ($this->arguments['multiple']) { + $storage = new ObjectStorage(); + $storage->attach($resource); + return $storage; + } + return $resource; + } + return $this->propertyMapper->convert($resource, FileReference::class); + } +} diff --git a/Classes/ViewHelpers/FormViewHelper.php b/Classes/ViewHelpers/FormViewHelper.php new file mode 100644 index 0000000..15fe29f --- /dev/null +++ b/Classes/ViewHelpers/FormViewHelper.php @@ -0,0 +1,92 @@ +getFormRuntime(); + $prefix = $this->prefixFieldName($this->getFormObjectName()); + + $markup = $this->createHiddenInputElement( + $prefix . '[__state]', + $this->hashService->appendHmac( + base64_encode(serialize($formRuntime->getFormState())), + HashScope::FormState->prefix(), + HashAlgo::SHA3_256 + ) + ); + + // ONLY assign `__session` if form is performing (uncached) + if ($formRuntime->canProcessFormSubmission() && $formRuntime->getFormSession() !== null) { + $markup .= $this->createHiddenInputElement( + $prefix . '[__session]', + $formRuntime->getFormSession()->getAuthenticatedIdentifier() + ); + } + return $markup; + } + + private function createHiddenInputElement(string $name, string $value): string + { + $tagBuilder = GeneralUtility::makeInstance(TagBuilder::class, 'input'); + $tagBuilder->addAttribute('type', 'hidden'); + $tagBuilder->addAttribute('name', $name); + $tagBuilder->addAttribute('value', $value); + return $tagBuilder->render(); + } + + /** + * We do NOT return NULL as in this case, the Form ViewHelpers do not enter $objectAccessorMode. + * However, we return the form identifier. + */ + protected function getFormObjectName(): string + { + return $this->getFormRuntime()->getFormDefinition()->getIdentifier(); + } + + private function getFormRuntime(): FormRuntime + { + return $this->arguments['object']; + } +} diff --git a/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php b/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php new file mode 100644 index 0000000..f863f4d --- /dev/null +++ b/Classes/ViewHelpers/GridColumnClassAutoConfigurationViewHelper.php @@ -0,0 +1,110 @@ +registerArgument('element', RootRenderableInterface::class, 'A RootRenderableInterface instance', true); + } + + public function render(): string + { + $formElement = $this->arguments['element']; + + if ($formElement instanceof RenderableInterface && !$formElement->isEnabled()) { + return ''; + } + + $gridRowElement = $formElement->getParentRenderable(); + $gridRowChildElements = $gridRowElement->getElements(); + $gridViewPortConfiguration = $gridRowElement->getProperties()['gridColumnClassAutoConfiguration']; + if (empty($gridViewPortConfiguration)) { + return ''; + } + $gridSize = (int)$gridViewPortConfiguration['gridSize']; + $columnsToCalculate = []; + $usedColumns = []; + foreach ($gridRowChildElements as $childElement) { + if ($childElement instanceof RenderableInterface && !$childElement->isEnabled()) { + continue; + } + if (empty($childElement->getProperties()['gridColumnClassAutoConfiguration'])) { + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + $columnsToCalculate[$viewPortName]['elements'] = ($columnsToCalculate[$viewPortName]['elements'] ?? 0) + 1; + } + } else { + $gridColumnViewPortConfiguration = $childElement->getProperties()['gridColumnClassAutoConfiguration']; + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + $configuration = $gridColumnViewPortConfiguration['viewPorts'][$viewPortName] ?? []; + if ( + isset($configuration['numbersOfColumnsToUse']) + && (int)$configuration['numbersOfColumnsToUse'] > 0 + ) { + $usedColumns[$viewPortName]['sum'] = ($usedColumns[$viewPortName]['sum'] ?? 0); + $usedColumns[$viewPortName]['sum'] += (int)$configuration['numbersOfColumnsToUse']; + if ($childElement->getIdentifier() === $formElement->getIdentifier()) { + $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] = (int)$configuration['numbersOfColumnsToUse']; + if ($usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] > $gridSize) { + $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'] = $gridSize; + } + } + } else { + $columnsToCalculate[$viewPortName]['elements'] = ($columnsToCalculate[$viewPortName]['elements'] ?? 0) + 1; + } + } + } + } + $classes = []; + foreach ($gridViewPortConfiguration['viewPorts'] as $viewPortName => $configuration) { + if (isset($usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse'])) { + $numbersOfColumnsToUse = $usedColumns[$viewPortName]['concreteNumbersOfColumnsToUse']; + } else { + $restColumnsToDivide = $gridSize - ($usedColumns[$viewPortName]['sum'] ?? 0); + $restElements = (int)$columnsToCalculate[$viewPortName]['elements']; + + if ($restColumnsToDivide < 1) { + $restColumnsToDivide = $gridSize; + } + $numbersOfColumnsToUse = floor($restColumnsToDivide / $restElements); + } + + $classes[] = str_replace( + '{@numbersOfColumnsToUse}', + (string)$numbersOfColumnsToUse, + $configuration['classPattern'] + ); + } + return implode(' ', $classes); + } +} diff --git a/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php b/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php new file mode 100644 index 0000000..d3d7b78 --- /dev/null +++ b/Classes/ViewHelpers/RenderAllFormValuesViewHelper.php @@ -0,0 +1,74 @@ +registerArgument('renderable', RootRenderableInterface::class, 'A RootRenderableInterface instance', true); + $this->registerArgument('as', 'string', 'The name within the template', false, 'formValue'); + } + + /** + * Return array element by key. + */ + public function render(): string + { + $renderable = $this->arguments['renderable']; + if ($renderable instanceof CompositeRenderableInterface) { + $elements = $renderable->getRenderablesRecursively(); + } else { + $elements = [$renderable]; + } + $as = $this->arguments['as']; + $output = ''; + foreach ($elements as $element) { + $output .= $this->renderingContext->getViewHelperInvoker()->invoke( + RenderFormValueViewHelper::class, + [ + 'renderable' => $element, + 'as' => $as, + ], + $this->renderingContext, + $this->renderChildren(...), + ); + } + return $output; + } +} diff --git a/Classes/ViewHelpers/RenderFormValueViewHelper.php b/Classes/ViewHelpers/RenderFormValueViewHelper.php new file mode 100644 index 0000000..1d6e015 --- /dev/null +++ b/Classes/ViewHelpers/RenderFormValueViewHelper.php @@ -0,0 +1,207 @@ +registerArgument('renderable', RenderableInterface::class, 'A renderable element', true); + $this->registerArgument('as', 'string', 'The name within the template', false, 'formValue'); + } + + /** + * Return array element by key + */ + public function render(): string + { + $element = $this->arguments['renderable']; + if (!$element instanceof FormElementInterface || !self::isEnabled($element)) { + return ''; + } + $renderingOptions = $element->getRenderingOptions(); + if ($renderingOptions['_isSection'] ?? false) { + $data = [ + 'element' => $element, + 'isSection' => true, + ]; + } elseif ($renderingOptions['_isCompositeFormElement'] ?? false) { + return ''; + } else { + $formRuntime = $this->renderingContext + ->getViewHelperVariableContainer() + ->get(RenderRenderableViewHelper::class, 'formRuntime'); + $value = $formRuntime[$element->getIdentifier()]; + $data = [ + 'element' => $element, + 'value' => $value, + 'processedValue' => $this->processElementValue($element, $value), + 'isMultiValue' => is_iterable($value), + ]; + } + $variableProvider = new ScopedVariableProvider($this->renderingContext->getVariableProvider(), new StandardVariableProvider([$this->arguments['as'] => $data])); + $this->renderingContext->setVariableProvider($variableProvider); + $output = (string)$this->renderChildren(); + $this->renderingContext->setVariableProvider($variableProvider->getGlobalVariableProvider()); + return $output; + } + + /** + * Converts the given value to a simple type (string or array) considering the underlying FormElement definition. + * + * @param mixed $value + * @return mixed + */ + private function processElementValue( + FormElementInterface $element, + $value + ) { + $properties = $element->getProperties(); + $options = $properties['options'] ?? null; + if ($element->getType() === 'CountrySelect') { + $country = $this->countryProvider->getByIsoCode($value ?? ''); + if ($country !== null) { + return (string)LocalizationUtility::translate($country->getLocalizedNameLabel()); + } + } + if (is_array($options)) { + $options = (array)$this->renderingContext->getViewHelperInvoker()->invoke( + TranslateElementPropertyViewHelper::class, + ['element' => $element, 'property' => 'options'], + $this->renderingContext, + $this->renderChildren(...), + ); + if (is_array($value)) { + return self::mapValuesToOptions($value, $options); + } + return self::mapValueToOption($value, $options); + } + if ($value instanceof ObjectStorage) { + $result = []; + foreach ($value as $item) { + $result[] = is_object($item) ? self::processObject($element, $item) : $item; + } + return $result; + } + if (is_object($value)) { + return self::processObject($element, $value); + } + return $value; + } + + /** + * Replaces the given values (=keys) with the corresponding elements in $options. + * + * @see mapValueToOption() + */ + private static function mapValuesToOptions(array $value, array $options): array + { + $result = []; + foreach ($value as $key) { + $result[] = self::mapValueToOption($key, $options); + } + return $result; + } + + /** + * Replaces the given value (=key) with the corresponding element in $options + * If the key does not exist in $options, it is returned without modification + * + * @param mixed $value + * @return mixed + */ + private static function mapValueToOption($value, array $options) + { + return $options[$value] ?? $value; + } + + /** + * Converts the given $object to a string representation considering the $element FormElement definition. + * + * @param object $object + */ + private static function processObject(FormElementInterface $element, $object): string + { + if ($element instanceof StringableFormElementInterface) { + return $element->valueToString($object); + } + + if ($object instanceof \DateTime) { + return $object->format(\DateTimeInterface::W3C); + } + + if ($object instanceof File || $object instanceof FileReference) { + if ($object instanceof FileReference) { + $object = $object->getOriginalResource(); + } + + return $object->getName(); + } + + if (method_exists($object, '__toString')) { + return (string)$object; + } + + return 'Object [' . get_class($object) . ']'; + } + + private static function isEnabled(RenderableInterface $renderable): bool + { + if (!$renderable->isEnabled()) { + return false; + } + while ($renderable = $renderable->getParentRenderable()) { + if (!$renderable->isEnabled()) { + return false; + } + } + return true; + } +} diff --git a/Classes/ViewHelpers/RenderRenderableViewHelper.php b/Classes/ViewHelpers/RenderRenderableViewHelper.php new file mode 100644 index 0000000..b175158 --- /dev/null +++ b/Classes/ViewHelpers/RenderRenderableViewHelper.php @@ -0,0 +1,84 @@ +registerArgument('renderable', RootRenderableInterface::class, 'A RenderableInterface instance', true); + } + + public function render(): string + { + /** @var FormRuntime $formRuntime */ + $formRuntime = $this->renderingContext + ->getViewHelperVariableContainer() + ->get(self::class, 'formRuntime'); + $renderable = $this->arguments['renderable']; + $this->eventDispatcher->dispatch(new BeforeRenderableIsRenderedEvent($renderable, $formRuntime)); + $content = ''; + if ($renderable instanceof FormRuntime || ($renderable instanceof RenderableInterface && $renderable->isEnabled())) { + $content = $this->renderChildren(); + } + // Wrap every renderable with a span with an identifier path data attribute if previewMode is active + if (!empty($content)) { + $renderingOptions = $formRuntime->getRenderingOptions(); + if (isset($renderingOptions['previewMode']) && $renderingOptions['previewMode'] === true) { + $path = $renderable->getIdentifier(); + if ($renderable instanceof RenderableInterface) { + while ($renderable = $renderable->getParentRenderable()) { + $path = $renderable->getIdentifier() . '/' . $path; + } + } + $content = '' . $content . ''; + } + } + return $content; + } +} diff --git a/Classes/ViewHelpers/RenderViewHelper.php b/Classes/ViewHelpers/RenderViewHelper.php new file mode 100644 index 0000000..5a25c14 --- /dev/null +++ b/Classes/ViewHelpers/RenderViewHelper.php @@ -0,0 +1,104 @@ + + * + * The factory class must implement :php:`TYPO3\CMS\Form\Domain\Factory\FormFactoryInterface`. + * + * Scope: frontend + * + * @see https://docs.typo3.org/permalink/t3viewhelper:typo3-form-render + */ +final class RenderViewHelper extends AbstractViewHelper +{ + /** + * @var bool + */ + protected $escapeOutput = false; + + public function __construct( + private readonly FormPersistenceManagerInterface $formPersistenceManager, + private readonly ExtbaseConfigurationManagerInterface $extbaseConfigurationManager, + ) {} + + public function initializeArguments(): void + { + $this->registerArgument('persistenceIdentifier', 'string', 'The persistence identifier for the form.'); + $this->registerArgument('factoryClass', 'string', 'The fully qualified class name of the factory', false, ArrayFormFactory::class); + $this->registerArgument('prototypeName', 'string', 'Name of the prototype to use'); + $this->registerArgument('overrideConfiguration', 'array', 'factory specific configuration', false, []); + } + + public function render(): ?string + { + $persistenceIdentifier = $this->arguments['persistenceIdentifier']; + $prototypeName = $this->arguments['prototypeName']; + $overrideConfiguration = $this->arguments['overrideConfiguration']; + /** @var RequestInterface $request */ + $request = $this->renderingContext->getAttribute(ServerRequestInterface::class); + // @todo: formvh:render() does not make sense without a persistenceIdentifier, does it? + if (!empty($persistenceIdentifier)) { + // The ConfigurationManager of ext:form needs ext:extbase ConfigurationManager to retrieve basic TS + // settings. ConfigurationManager of extbase should *usually* only be called in extbase context and + // needs a Request, which is usually set by extbase bootstrap. + // We are however (most likely) not in extbase context here. + // To prevent a fallback of extbase ConfigurationManager to $GLOBALS['TYPO3_REQUEST'], we set + // the request explicitly here, to then fetch $formSettings from ext:form ConfigurationManager. + // $typoScriptSettings is hand over to load() to apply TS overrides for single forms, see #92408. + $this->extbaseConfigurationManager->setRequest($request); + $typoScriptSettings = $this->extbaseConfigurationManager->getConfiguration(ExtbaseConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS, 'form'); + $formConfiguration = $this->formPersistenceManager->load($persistenceIdentifier, $typoScriptSettings, $request); + ArrayUtility::mergeRecursiveWithOverrule($formConfiguration, $overrideConfiguration); + $overrideConfiguration = $formConfiguration; + $overrideConfiguration['persistenceIdentifier'] = $persistenceIdentifier; + } + if (empty($prototypeName)) { + $prototypeName = $overrideConfiguration['prototypeName'] ?? 'standard'; + } + // Even though getContainer() is internal, we can't get container injected here due to static scope + /** @var FormFactoryInterface $factory */ + $factory = GeneralUtility::getContainer()->get($this->arguments['factoryClass']); + $formDefinition = $factory->build($overrideConfiguration, $prototypeName, $request); + $form = $formDefinition->bind($request); + return $form->render(); + } +} diff --git a/Classes/ViewHelpers/TranslateElementErrorViewHelper.php b/Classes/ViewHelpers/TranslateElementErrorViewHelper.php new file mode 100644 index 0000000..9d72eca --- /dev/null +++ b/Classes/ViewHelpers/TranslateElementErrorViewHelper.php @@ -0,0 +1,61 @@ +registerArgument('element', RootRenderableInterface::class, 'Form Element to translate', true); + $this->registerArgument('error', Error::class, 'Error', true); + } + + public function render(): string + { + $element = $this->arguments['element']; + $error = $this->arguments['error']; + /** @var FormRuntime $formRuntime */ + $formRuntime = $this->renderingContext + ->getViewHelperVariableContainer() + ->get(RenderRenderableViewHelper::class, 'formRuntime'); + return $this->translationService->translateFormElementError( + $element, + $error->getCode(), + $error->getArguments(), + $error->__toString(), + $formRuntime + ); + } +} diff --git a/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php b/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php new file mode 100644 index 0000000..fe4e923 --- /dev/null +++ b/Classes/ViewHelpers/TranslateElementPropertyViewHelper.php @@ -0,0 +1,93 @@ +registerArgument('element', RootRenderableInterface::class, 'Form Element to translate', true); + $this->registerArgument('property', 'mixed', 'Property to translate'); + $this->registerArgument('renderingOptionProperty', 'mixed', 'Property to translate'); + $this->registerArgument('languageKey', 'string', 'Language key ("da" for example) or "default" to use. Also a Locale object is possible. If empty, use current locale from the request.'); + } + + /** + * Return array element by key. + */ + public function render(): array|string|null + { + self::assertArgumentTypes($this->arguments); + $element = $this->arguments['element']; + $property = null; + if (!empty($this->arguments['property'])) { + $property = $this->arguments['property']; + } elseif (!empty($this->arguments['renderingOptionProperty'])) { + $property = $this->arguments['renderingOptionProperty']; + } + if (empty($property)) { + $propertyParts = []; + } elseif (is_array($property)) { + $propertyParts = $property; + } else { + $propertyParts = [$property]; + } + /** @var FormRuntime $formRuntime */ + $formRuntime = $this->renderingContext + ->getViewHelperVariableContainer() + ->get(RenderRenderableViewHelper::class, 'formRuntime'); + return $this->translationService->translateFormElementValue($element, $propertyParts, $formRuntime, $this->arguments['languageKey']); + } + + private static function assertArgumentTypes(array $arguments): void + { + foreach (['property', 'renderingOptionProperty'] as $argumentName) { + if ( + !isset($arguments[$argumentName]) + || is_string($arguments[$argumentName]) + || is_array($arguments[$argumentName]) + ) { + continue; + } + throw new InvalidArgumentValueException( + sprintf( + 'Arguments "%s" either must be string or array', + $argumentName + ), + 1504871830 + ); + } + } +} diff --git a/Configuration/Backend/Modules.php b/Configuration/Backend/Modules.php new file mode 100644 index 0000000..83e5f8b --- /dev/null +++ b/Configuration/Backend/Modules.php @@ -0,0 +1,46 @@ + [ + 'parent' => 'content', + 'position' => ['after' => 'workspaces_admin'], + 'access' => 'user', + 'path' => '/module/form', + 'iconIdentifier' => 'module-form', + 'labels' => 'form.module', + 'inheritNavigationComponentFromMainModule' => false, + ], + 'form_manager' => [ + 'parent' => 'web_FormFormbuilder', + 'access' => 'user', + 'path' => '/module/form/overview', + 'iconIdentifier' => 'module-form', + 'labels' => 'form.modules.form_manager', + 'extensionName' => 'Form', + 'controllerActions' => [ + FormManagerController::class => [ + 'index', 'show', 'create', 'duplicate', 'references', 'delete', + ], + ], + ], + 'form_editor' => [ + 'parent' => 'web_FormFormbuilder', + 'access' => 'user', + 'path' => '/module/form/editor', + 'iconIdentifier' => 'module-form', + 'navigationComponent' => '@typo3/form/backend/form-editor-tree-container', + 'labels' => 'form.modules.form_editor', + 'extensionName' => 'Form', + 'controllerActions' => [ + FormEditorController::class => [ + 'index', 'saveForm', 'renderFormPage', + ], + ], + ], +]; diff --git a/Configuration/ExpressionLanguage.php b/Configuration/ExpressionLanguage.php new file mode 100644 index 0000000..c03a2bd --- /dev/null +++ b/Configuration/ExpressionLanguage.php @@ -0,0 +1,8 @@ + [ + \TYPO3\CMS\Core\ExpressionLanguage\TypoScriptConditionProvider::class, + \TYPO3\CMS\Form\Domain\Condition\ConditionProvider::class, + ], +]; diff --git a/Configuration/Extbase/Persistence/Classes.php b/Configuration/Extbase/Persistence/Classes.php new file mode 100644 index 0000000..cb64483 --- /dev/null +++ b/Configuration/Extbase/Persistence/Classes.php @@ -0,0 +1,9 @@ + [ + 'tableName' => 'sys_file_reference', + ], +]; diff --git a/Configuration/FlexForms/FormFramework.xml b/Configuration/FlexForms/FormFramework.xml new file mode 100644 index 0000000..ee32bc1 --- /dev/null +++ b/Configuration/FlexForms/FormFramework.xml @@ -0,0 +1,27 @@ + + + + + LLL:EXT:form/Resources/Private/Language/Database.xlf:tt_content.pi_flexform.formframework.sheet_general + array + + + + reload + + select + selectSingle + + + + + + + formPersistenceIdentifier + + + + + + + diff --git a/Configuration/Fluid/Namespaces.php b/Configuration/Fluid/Namespaces.php new file mode 100644 index 0000000..add7bbd --- /dev/null +++ b/Configuration/Fluid/Namespaces.php @@ -0,0 +1,7 @@ + [ + 'TYPO3\\CMS\\Form\\ViewHelpers', + ], +]; diff --git a/Configuration/Form/Base/Finishers/Closure.yaml b/Configuration/Form/Base/Finishers/Closure.yaml new file mode 100644 index 0000000..1d824ab --- /dev/null +++ b/Configuration/Form/Base/Finishers/Closure.yaml @@ -0,0 +1,12 @@ +prototypes: + standard: + finishersDefinition: + Closure: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\ClosureFinisher + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Closure.editor.header.label + predefinedDefaults: + options: + closure: '' + errorMessage: '' diff --git a/Configuration/Form/Base/Finishers/Confirmation.yaml b/Configuration/Form/Base/Finishers/Confirmation.yaml new file mode 100644 index 0000000..64dc01b --- /dev/null +++ b/Configuration/Form/Base/Finishers/Confirmation.yaml @@ -0,0 +1,46 @@ +prototypes: + standard: + finishersDefinition: + Confirmation: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher + options: + templateName: Confirmation + # @todo: These paths are unfortunate. They should in general be + # "EXT:form/Resources/Private/(Templates / Layout / Partials), + # and then "Frontend/Finishers/Confirmation/Confirmation" as templateName + # to be fed to render(), to follow general core view rendering practice + # of having global "extension entry paths". Create some b/w compat layer, + # move position of default templates around and deprecate the old way. + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Confirmation/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layout/Finishers/Confirmation/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/Finishers/Confirmation/' + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + predefinedDefaults: + options: + message: '' + contentElementUid: '' + errorMessage: '' + FormEngine: + label: tt_content.finishersDefinition.Confirmation.label + elements: + contentElementUid: + label: tt_content.finishersDefinition.Confirmation.contentElementUid.label + config: + type: group + allowed: tt_content + size: 1 + maxitems: 1 + fieldWizard: + recordsOverview: + disabled: 1 + message: + label: tt_content.finishersDefinition.Confirmation.message.label + config: + type: text + enableRichtext: true + richtextConfiguration: form-content diff --git a/Configuration/Form/Base/Finishers/DeleteUploads.yaml b/Configuration/Form/Base/Finishers/DeleteUploads.yaml new file mode 100644 index 0000000..44f2aeb --- /dev/null +++ b/Configuration/Form/Base/Finishers/DeleteUploads.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + finishersDefinition: + DeleteUploads: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\DeleteUploadsFinisher + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label diff --git a/Configuration/Form/Base/Finishers/EmailToReceiver.yaml b/Configuration/Form/Base/Finishers/EmailToReceiver.yaml new file mode 100644 index 0000000..6fcaa8a --- /dev/null +++ b/Configuration/Form/Base/Finishers/EmailToReceiver.yaml @@ -0,0 +1,161 @@ +prototypes: + standard: + finishersDefinition: + EmailToReceiver: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\EmailFinisher + options: + templateName: 'Default' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Email/' + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + predefinedDefaults: + options: + subject: '' + recipients: { } + senderAddress: '' + senderName: '' + replyToRecipients: { } + carbonCopyRecipients: { } + blindCarbonCopyRecipients: { } + addHtmlPart: true + attachUploads: true + translation: + language: '' + title: '' + message: '' + errorMessage: '' + FormEngine: + label: tt_content.finishersDefinition.EmailToReceiver.label + elements: + message: + label: tt_content.finishersDefinition.EmailToReceiver.message.label + config: + type: text + enableRichtext: true + richtextConfiguration: form-content + subject: + label: tt_content.finishersDefinition.EmailToReceiver.subject.label + config: + type: input + required: true + recipients: + title: tt_content.finishersDefinition.EmailToReceiver.recipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.recipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + senderAddress: + label: tt_content.finishersDefinition.EmailToReceiver.senderAddress.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + senderName: + label: tt_content.finishersDefinition.EmailToReceiver.senderName.label + config: + type: input + replyToRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.replyToRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + carbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.carbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + blindCarbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.blindCarbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + addHtmlPart: + label: tt_content.finishersDefinition.EmailToReceiver.addHtmlPart.label + config: + type: check + default: 1 + translation: + language: + label: tt_content.finishersDefinition.EmailToReceiver.language.label + config: + type: select + renderType: selectSingle + minitems: 1 + maxitems: 1 + size: 1 + items: + 5: + label: tt_content.finishersDefinition.EmailToReceiver.language.0 + value: '' + 10: + label: tt_content.finishersDefinition.EmailToReceiver.language.1 + value: default + title: + label: tt_content.finishersDefinition.EmailToReceiver.title.label + config: + type: input diff --git a/Configuration/Form/Base/Finishers/EmailToSender.yaml b/Configuration/Form/Base/Finishers/EmailToSender.yaml new file mode 100644 index 0000000..e9c4ff0 --- /dev/null +++ b/Configuration/Form/Base/Finishers/EmailToSender.yaml @@ -0,0 +1,161 @@ +prototypes: + standard: + finishersDefinition: + EmailToSender: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\EmailFinisher + options: + templateName: 'Default' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Email/' + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + predefinedDefaults: + options: + subject: '' + recipients: { } + senderAddress: '' + senderName: '' + replyToRecipients: { } + carbonCopyRecipients: { } + blindCarbonCopyRecipients: { } + addHtmlPart: true + attachUploads: true + title: '' + message: '' + translation: + language: '' + errorMessage: '' + FormEngine: + label: tt_content.finishersDefinition.EmailToSender.label + elements: + message: + label: tt_content.finishersDefinition.EmailToSender.message.label + config: + type: text + enableRichtext: true + richtextConfiguration: form-content + subject: + label: tt_content.finishersDefinition.EmailToSender.subject.label + config: + type: input + required: true + recipients: + title: tt_content.finishersDefinition.EmailToSender.recipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.recipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + senderAddress: + label: tt_content.finishersDefinition.EmailToSender.senderAddress.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + senderName: + label: tt_content.finishersDefinition.EmailToSender.senderName.label + config: + type: input + replyToRecipients: + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + carbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + blindCarbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: input + eval: TYPO3\CMS\Form\Evaluation\EmailOrFormElementIdentifier + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + addHtmlPart: + label: tt_content.finishersDefinition.EmailToSender.addHtmlPart.label + config: + type: check + default: 1 + translation: + language: + label: tt_content.finishersDefinition.EmailToSender.language.label + config: + type: select + renderType: selectSingle + minitems: 1 + maxitems: 1 + size: 1 + items: + 5: + label: tt_content.finishersDefinition.EmailToSender.language.0 + value: '' + 10: + label: tt_content.finishersDefinition.EmailToSender.language.1 + value: default + title: + label: tt_content.finishersDefinition.EmailToSender.title.label + config: + type: input diff --git a/Configuration/Form/Base/Finishers/FlashMessage.yaml b/Configuration/Form/Base/Finishers/FlashMessage.yaml new file mode 100644 index 0000000..1f11049 --- /dev/null +++ b/Configuration/Form/Base/Finishers/FlashMessage.yaml @@ -0,0 +1,16 @@ +prototypes: + standard: + finishersDefinition: + FlashMessage: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\FlashMessageFinisher + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + predefinedDefaults: + options: + messageBody: '' + messageTitle: '' + messageArguments: '' + messageCode: 0 + severity: 0 + errorMessage: '' diff --git a/Configuration/Form/Base/Finishers/Redirect.yaml b/Configuration/Form/Base/Finishers/Redirect.yaml new file mode 100644 index 0000000..eb1137d --- /dev/null +++ b/Configuration/Form/Base/Finishers/Redirect.yaml @@ -0,0 +1,36 @@ +prototypes: + standard: + finishersDefinition: + Redirect: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\RedirectFinisher + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + predefinedDefaults: + options: + pageUid: '' + additionalParameters: '' + fragment: '' + errorMessage: '' + FormEngine: + label: tt_content.finishersDefinition.Redirect.label + elements: + pageUid: + label: tt_content.finishersDefinition.Redirect.pageUid.label + config: + type: group + allowed: pages + size: 1 + minitems: 1 + maxitems: 1 + fieldWizard: + recordsOverview: + disabled: 1 + additionalParameters: + label: tt_content.finishersDefinition.Redirect.additionalParameters.label + config: + type: input + fragment: + label: tt_content.finishersDefinition.Redirect.fragment.label + config: + type: input diff --git a/Configuration/Form/Base/Finishers/SaveToDatabase.yaml b/Configuration/Form/Base/Finishers/SaveToDatabase.yaml new file mode 100644 index 0000000..a3c3ec0 --- /dev/null +++ b/Configuration/Form/Base/Finishers/SaveToDatabase.yaml @@ -0,0 +1,11 @@ +prototypes: + standard: + finishersDefinition: + SaveToDatabase: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\SaveToDatabaseFinisher + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + predefinedDefaults: + options: + errorMessage: '' diff --git a/Configuration/Form/Base/FormElements/AdvancedPassword.yaml b/Configuration/Form/Base/FormElements/AdvancedPassword.yaml new file mode 100644 index 0000000..c455d74 --- /dev/null +++ b/Configuration/Form/Base/FormElements/AdvancedPassword.yaml @@ -0,0 +1,342 @@ +prototypes: + standard: + formElementsDefinition: + AdvancedPassword: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: confirmationLabel + templateName: Inspector-TextEditor + label: formEditor.elements.AdvancedPassword.editor.confirmationLabel.label + propertyPath: properties.confirmationLabel + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'new-password' + label: formEditor.elements.FormElement.editor.autocomplete.option.new-password + 30: + value: 'current-password' + label: formEditor.elements.FormElement.editor.autocomplete.option.current-password + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + confirmationLabel: formEditor.element.AdvancedPassword.editor.confirmationLabel.predefinedDefaults + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.AdvancedPassword.label + description: formEditor.elements.AdvancedPassword.description + group: custom + groupSorting: 500 + iconIdentifier: form-advanced-password + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + renderFieldset: 1 + fieldsetClassAttribute: 'form-element form-element-advancedpassword mb-3' + containerClassAttribute: 'form-element mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + confirmationLabel: '' + confirmationClassAttribute: form-control diff --git a/Configuration/Form/Base/FormElements/Checkbox.yaml b/Configuration/Form/Base/FormElements/Checkbox.yaml new file mode 100644 index 0000000..0a4e9b4 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Checkbox.yaml @@ -0,0 +1,109 @@ +prototypes: + standard: + formElementsDefinition: + Checkbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextareaEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + enableRichtext: true + richtextConfiguration: form-label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 30: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 70: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Checkbox.label + description: formEditor.elements.Checkbox.description + group: select + groupSorting: 100 + iconIdentifier: form-checkbox + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-check mb-3' + elementClassAttribute: form-check-input + elementErrorClassAttribute: ~ + labelClassAttribute: form-check-wrapping-label + labelTextClassAttribute: form-check-label + value: 1 diff --git a/Configuration/Form/Base/FormElements/ContentElement.yaml b/Configuration/Form/Base/FormElements/ContentElement.yaml new file mode 100644 index 0000000..1530e38 --- /dev/null +++ b/Configuration/Form/Base/FormElements/ContentElement.yaml @@ -0,0 +1,76 @@ +prototypes: + standard: + formElementsDefinition: + ContentElement: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.ContentElement.editor.contentElement.label + buttonLabel: formEditor.elements.ContentElement.editor.contentElement.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: properties.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + label: formEditor.elements.ContentElement.label + properties: + contentElementUid: '' + label: formEditor.elements.ContentElement.label + description: formEditor.elements.ContentElement.description + group: custom + groupSorting: 700 + iconIdentifier: form-content-element + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + contentElementUid: '' + outerContainerClassAttribute: clearfix + variants: + - + identifier: hide-1 + renderingOptions: + enabled: false + condition: 'stepType == "SummaryPage" || finisherIdentifier in ["EmailToSender", "EmailToReceiver"]' diff --git a/Configuration/Form/Base/FormElements/CountrySelect.yaml b/Configuration/Form/Base/FormElements/CountrySelect.yaml new file mode 100644 index 0000000..3750cab --- /dev/null +++ b/Configuration/Form/Base/FormElements/CountrySelect.yaml @@ -0,0 +1,134 @@ +prototypes: + standard: + formElementsDefinition: + CountrySelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 245: + identifier: defaultValue + templateName: Inspector-CountrySingleSelectEditor + label: formEditor.elements.CountrySelect.editor.defaultValue.label + propertyPath: defaultValue + description: formEditor.elements.CountrySelect.editor.defaultValue.description + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true + 300: + identifier: prioritizedCountries + templateName: Inspector-CountrySelectEditor + label: formEditor.elements.CountrySelect.editor.prioritizedCountries.label + propertyPath: properties.prioritizedCountries + 310: + identifier: onlyCountries + templateName: Inspector-CountrySelectEditor + label: formEditor.elements.CountrySelect.editor.onlyCountries.label + propertyPath: properties.onlyCountries + 320: + identifier: excludeCountries + templateName: Inspector-CountrySelectEditor + label: formEditor.elements.CountrySelect.editor.excludeCountries.label + propertyPath: properties.excludeCountries + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'country' + label: formEditor.elements.FormElement.editor.autocomplete.option.country + 30: + value: 'country-name' + label: formEditor.elements.FormElement.editor.autocomplete.option.country-name + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + properties: + options: { } + label: formEditor.elements.CountrySelect.label + description: formEditor.elements.CountrySelect.description + group: select + groupSorting: 200 + iconIdentifier: form-multi-select + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-select mb-3' + elementClassAttribute: form-select + elementErrorClassAttribute: ~ + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/Date.yaml b/Configuration/Form/Base/FormElements/Date.yaml new file mode 100644 index 0000000..35b9193 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Date.yaml @@ -0,0 +1,351 @@ +prototypes: + standard: + formElementsDefinition: + Date: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: defaultValue + templateName: Inspector-DateEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + propertyValidators: + 10: RFC3339FullDateOrEmpty + 550: + identifier: step + templateName: Inspector-TextEditor + label: formEditor.elements.Date.editor.step.label + description: formEditor.elements.Date.editor.step.description + propertyPath: properties.fluidAdditionalAttributes.step + propertyValidators: + 10: Integer + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'bday' + label: formEditor.elements.FormElement.editor.autocomplete.option.bday + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: DateRange + label: formEditor.elements.Date.editor.validators.DateRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + properties: + fluidAdditionalAttributes: + min: '' + max: '' + step: 1 + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.header.label + 250: + identifier: minimum + templateName: Inspector-DateEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.minimum + propertyPath: options.minimum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-DateEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.maximum + propertyPath: options.maximum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1521293685 + 20: 1521293686 + 30: 1521293687 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Date.label + description: formEditor.elements.Date.description + group: html5 + groupSorting: 500 + iconIdentifier: form-date-picker + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Date + properties: + containerClassAttribute: 'form-element form-element-date mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' diff --git a/Configuration/Form/Base/FormElements/Email.yaml b/Configuration/Form/Base/FormElements/Email.yaml new file mode 100644 index 0000000..ea708a1 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Email.yaml @@ -0,0 +1,324 @@ +prototypes: + standard: + formElementsDefinition: + Email: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + propertyValidators: + 10: NaiveEmailOrEmpty + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'email' + label: formEditor.elements.FormElement.editor.autocomplete.option.email + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + validators: + - + identifier: EmailAddress + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Email.label + description: formEditor.elements.Email.description + group: html5 + groupSorting: 100 + iconIdentifier: form-email + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-email mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + validators: + - + identifier: EmailAddress diff --git a/Configuration/Form/Base/FormElements/Fieldset.yaml b/Configuration/Form/Base/FormElements/Fieldset.yaml new file mode 100644 index 0000000..ccf2b29 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Fieldset.yaml @@ -0,0 +1,64 @@ +prototypes: + standard: + formElementsDefinition: + Fieldset: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Fieldset.editor.label.label + propertyPath: label + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Fieldset.label + description: formEditor.elements.Fieldset.description + group: container + groupSorting: 100 + _isCompositeFormElement: true + iconIdentifier: form-fieldset + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Section + properties: + containerClassAttribute: ~ + elementClassAttribute: 'form-element form-element-fieldset mb-3' + elementErrorClassAttribute: ~ + renderingOptions: + _isCompositeFormElement: true + _isSection: true diff --git a/Configuration/Form/Base/FormElements/FileUpload.yaml b/Configuration/Form/Base/FormElements/FileUpload.yaml new file mode 100644 index 0000000..9311dbf --- /dev/null +++ b/Configuration/Form/Base/FormElements/FileUpload.yaml @@ -0,0 +1,220 @@ +prototypes: + standard: + formElementsDefinition: + FileUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: application/msword + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.doc + 20: + value: application/vnd.openxmlformats-officedocument.wordprocessingml.document + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.docx + 30: + value: application/msexcel + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xls + 40: + value: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xlsx + 50: + value: application/pdf + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.pdf + 60: + value: application/vnd.oasis.opendocument.text + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.odt + 70: + value: application/vnd.oasis.opendocument.spreadsheet-template + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.ods + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + 500: + identifier: multiple + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FileUpload.editor.multiple.label + propertyPath: properties.multiple + 550: + identifier: allowRemoval + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FileUpload.editor.allowRemoval.label + propertyPath: properties.allowRemoval + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'photo' + label: formEditor.elements.FormElement.editor.autocomplete.option.photo + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.FileUploadMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label + 20: + value: FileSize + label: formEditor.elements.FileUploadMixin.editor.validators.FileSize.label + 30: + value: Count + label: formEditor.elements.FileUploadMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/pdf + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 150: + identifier: maximumFileSize + templateName: Inspector-MaximumFileSizeEditor + label: formEditor.elements.FileUpload.editor.maximumFileSize.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.FileUpload.label + description: formEditor.elements.FileUpload.description + group: custom + groupSorting: 100 + iconIdentifier: form-file-upload + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload + properties: + containerClassAttribute: 'form-element form-element-fileupload mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: [] diff --git a/Configuration/Form/Base/FormElements/Form.yaml b/Configuration/Form/Base/FormElements/Form.yaml new file mode 100644 index 0000000..a5b55f7 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Form.yaml @@ -0,0 +1,520 @@ +prototypes: + standard: + formElementsDefinition: + Form: + formEditor: + predefinedDefaults: + renderingOptions: + submitButtonLabel: formEditor.elements.Form.editor.submitButtonLabel.value + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.BaseFormElementMixin.editor.label.label + propertyPath: label + 300: + identifier: submitButtonLabel + templateName: Inspector-TextEditor + label: formEditor.elements.Form.editor.submitButtonLabel.label + propertyPath: renderingOptions.submitButtonLabel + 900: + identifier: finishers + templateName: Inspector-FinishersEditor + label: formEditor.elements.Form.editor.finishers.label + selectOptions: + 10: + value: '' + label: formEditor.elements.Form.editor.finishers.EmptyValue.label + 20: + value: EmailToSender + label: formEditor.elements.Form.editor.finishers.EmailToSender.label + 30: + value: EmailToReceiver + label: formEditor.elements.Form.editor.finishers.EmailToReceiver.label + 40: + value: Redirect + label: formEditor.elements.Form.editor.finishers.Redirect.label + 50: + value: DeleteUploads + label: formEditor.elements.Form.editor.finishers.DeleteUploads.label + 60: + value: Confirmation + label: formEditor.elements.Form.editor.finishers.Confirmation.label + _isCompositeFormElement: false + _isTopLevelFormElement: true + saveSuccessFlashMessageTitle: formEditor.elements.Form.saveSuccessFlashMessageTitle + saveSuccessFlashMessageMessage: formEditor.elements.Form.saveSuccessFlashMessageMessage + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage + modalValidationErrorsDialogTitle: formEditor.modals.validationErrors.dialogTitle + modalValidationErrorsConfirmButton: formEditor.modals.validationErrors.confirmButton + modalInsertElementsDialogTitle: formEditor.modals.insertElements.dialogTitle + modalInsertPagesDialogTitle: formEditor.modals.newPages.dialogTitle + modalCloseDialogMessage: formEditor.modals.close.dialogMessage + modalCloseDialogTitle: formEditor.modals.close.dialogTitle + modalCloseConfirmButton: formEditor.modals.close.confirmButton + modalCloseCancelButton: formEditor.modals.close.cancelButton + modalRemoveElementDialogTitle: formEditor.modals.removeElement.dialogTitle + modalRemoveElementDialogMessage: formEditor.modals.removeElement.dialogMessage + modalRemoveElementConfirmButton: formEditor.modals.removeElement.confirmButton + modalRemoveElementCancelButton: formEditor.modals.removeElement.cancelButton + modalRemoveElementLastAvailablePageFlashMessageTitle: formEditor.modals.removeElement.lastAvailablePageFlashMessageTitle + modalRemoveElementLastAvailablePageFlashMessageMessage: formEditor.modals.removeElement.lastAvailablePageFlashMessageMessage + paginationTitle: formEditor.pagination.title + iconIdentifier: content-form + propertyCollections: + finishers: + 10: + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 250: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.EmailToSender.editor.message.description + enableRichtext: true + richtextConfiguration: form-content + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + description: formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.description + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + description: formEditor.elements.Form.finisher.EmailToSender.editor.senderName.description + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.label + propertyPath: options.translation.language + selectOptions: + 5: + value: '' + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.0 + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToSender.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + identifier: EmailToSender + 20: + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 250: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.message.description + enableRichtext: true + richtextConfiguration: form-content + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.description + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.description + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label + propertyPath: options.translation.language + selectOptions: + 5: + value: '' + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.0 + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + identifier: EmailToReceiver + 30: + identifier: Redirect + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + 200: + identifier: pageUid + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.pageUid.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel + browsableType: pages + iconIdentifier: apps-pagetree-page-default + propertyPath: options.pageUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: additionalParameters + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label + propertyPath: options.additionalParameters + 400: + identifier: fragment + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.fragment.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.fragment.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.fragment + description: formEditor.elements.Form.finisher.Redirect.editor.fragment.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: DeleteUploads + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Confirmation + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + 200: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.label + buttonLabel: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: IntegerOrEmpty + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.Confirmation.editor.message.description + enableRichtext: true + richtextConfiguration: form-content + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Closure + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Closure.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: FlashMessage + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: SaveToDatabase + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + rendererClassName: TYPO3\CMS\Form\Domain\Renderer\FluidFormRenderer + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + fieldProperties: + errorMsgClassAttribute: invalid-feedback + errorClassAttribute: is-invalid + descriptionClassAttribute: form-text + requiredMarkClassAttribute: required + visuallyHiddenClassAttribute: visually-hidden + formNavigation: + navigationWrapperClassAttribute: actions + navigationClassAttribute: form-navigation + navigationAriaLabelAttribute: Form Navigation + btnPreviousClassAttribute: 'btn btn-outline-primary' + btnNextClassAttribute: 'btn btn-primary' + btnSubmitClassAttribute: 'btn btn-primary' diff --git a/Configuration/Form/Base/FormElements/GridColumn.yaml b/Configuration/Form/Base/FormElements/GridColumn.yaml new file mode 100644 index 0000000..00ea2a7 --- /dev/null +++ b/Configuration/Form/Base/FormElements/GridColumn.yaml @@ -0,0 +1,59 @@ +prototypes: + standard: + formElementsDefinition: + GridColumn: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.GridColumn.editor.label.label + propertyPath: label + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.GridColumn.label + description: formEditor.elements.GridColumn.description + group: container + groupSorting: 400 + _isCompositeFormElement: true + iconIdentifier: form-gridcolumn + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GridColumn + renderingOptions: + _isCompositeFormElement: true diff --git a/Configuration/Form/Base/FormElements/GridRow.yaml b/Configuration/Form/Base/FormElements/GridRow.yaml new file mode 100644 index 0000000..4eff4bb --- /dev/null +++ b/Configuration/Form/Base/FormElements/GridRow.yaml @@ -0,0 +1,80 @@ +prototypes: + standard: + formElementsDefinition: + GridRow: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.GridRow.editor.label.label + propertyPath: label + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.GridRow.label + description: formEditor.elements.GridRow.description + group: container + groupSorting: 300 + _isCompositeFormElement: true + _isGridRowFormElement: true + iconIdentifier: form-gridrow + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GridRow + properties: + containerClassAttribute: ~ + elementClassAttribute: 'form-element form-element-gridrow row' + elementErrorClassAttribute: ~ + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + xl: + classPattern: 'col-xl-{@numbersOfColumnsToUse}' + xxl: + classPattern: 'col-xxl-{@numbersOfColumnsToUse}' + renderingOptions: + _isCompositeFormElement: true + _isGridRowFormElement: true diff --git a/Configuration/Form/Base/FormElements/Hidden.yaml b/Configuration/Form/Base/FormElements/Hidden.yaml new file mode 100644 index 0000000..f435e81 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Hidden.yaml @@ -0,0 +1,86 @@ +prototypes: + standard: + formElementsDefinition: + Hidden: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.Hidden.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + label: formEditor.elements.Hidden.label + description: formEditor.elements.Hidden.description + group: custom + groupSorting: 300 + iconIdentifier: form-hidden + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-hidden' + elementClassAttribute: '' + elementErrorClassAttribute: ~ + variants: + - + identifier: hide-1 + renderingOptions: + enabled: false + condition: 'stepType == "SummaryPage" || finisherIdentifier in ["EmailToSender", "EmailToReceiver"]' diff --git a/Configuration/Form/Base/FormElements/Honeypot.yaml b/Configuration/Form/Base/FormElements/Honeypot.yaml new file mode 100644 index 0000000..88821df --- /dev/null +++ b/Configuration/Form/Base/FormElements/Honeypot.yaml @@ -0,0 +1,328 @@ +prototypes: + standard: + formElementsDefinition: + Honeypot: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: form-element + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + variants: + - + identifier: hide-1 + renderingOptions: + enabled: false + condition: 'stepType == "SummaryPage" || finisherIdentifier in ["EmailToSender", "EmailToReceiver"]' diff --git a/Configuration/Form/Base/FormElements/ImageUpload.yaml b/Configuration/Form/Base/FormElements/ImageUpload.yaml new file mode 100644 index 0000000..ecaba44 --- /dev/null +++ b/Configuration/Form/Base/FormElements/ImageUpload.yaml @@ -0,0 +1,211 @@ +prototypes: + standard: + formElementsDefinition: + ImageUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: image/jpeg + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.jpg + 20: + value: image/png + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.png + 30: + value: image/bmp + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.bmp + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + 500: + identifier: multiple + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FileUpload.editor.multiple.label + propertyPath: properties.multiple + 550: + identifier: allowRemoval + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FileUpload.editor.allowRemoval.label + propertyPath: properties.allowRemoval + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'photo' + label: formEditor.elements.FormElement.editor.autocomplete.option.photo + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.FileUploadMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label + 20: + value: FileSize + label: formEditor.elements.FileUploadMixin.editor.validators.FileSize.label + 30: + value: Count + label: formEditor.elements.FileUploadMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 150: + identifier: maximumFileSize + templateName: Inspector-MaximumFileSizeEditor + label: formEditor.elements.FileUpload.editor.maximumFileSize.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.ImageUpload.label + description: formEditor.elements.ImageUpload.description + group: custom + groupSorting: 400 + iconIdentifier: form-image-upload + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload + properties: + containerClassAttribute: 'form-element form-element-imageupload mb-3' + elementClassAttribute: 'form-control lightbox' + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: [] + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 diff --git a/Configuration/Form/Base/FormElements/MultiCheckbox.yaml b/Configuration/Form/Base/FormElements/MultiCheckbox.yaml new file mode 100644 index 0000000..942b579 --- /dev/null +++ b/Configuration/Form/Base/FormElements/MultiCheckbox.yaml @@ -0,0 +1,169 @@ +prototypes: + standard: + formElementsDefinition: + MultiCheckbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + propertyValidators: + 10: NotEmpty + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 30: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 70: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.validationErrorMessage.label + description: formEditor.elements.MultiSelectionMixin.validators.Count.editor.validationErrorMessage.description + errorCodes: + 10: 1475002976 + 20: 1475002994 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.MultiCheckbox.label + description: formEditor.elements.MultiCheckbox.description + group: select + groupSorting: 400 + iconIdentifier: form-multi-checkbox + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + renderFieldset: 1 + fieldsetClassAttribute: 'form-element form-element-radio mb-3' + containerClassAttribute: 'form-check mb-2' + elementClassAttribute: form-check-input + elementErrorClassAttribute: ~ + labelClassAttribute: form-check-wrapping-label + labelTextClassAttribute: form-check-label + legendVisuallyHidden: 0 diff --git a/Configuration/Form/Base/FormElements/MultiSelect.yaml b/Configuration/Form/Base/FormElements/MultiSelect.yaml new file mode 100644 index 0000000..fc5d6ed --- /dev/null +++ b/Configuration/Form/Base/FormElements/MultiSelect.yaml @@ -0,0 +1,174 @@ +prototypes: + standard: + formElementsDefinition: + MultiSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + propertyValidators: + 10: NotEmpty + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 30: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 70: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.validationErrorMessage.label + description: formEditor.elements.MultiSelectionMixin.validators.Count.editor.validationErrorMessage.description + errorCodes: + 10: 1475002976 + 20: 1475002994 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.MultiSelect.label + description: formEditor.elements.MultiSelect.description + group: select + groupSorting: 500 + iconIdentifier: form-multi-select + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-multiselect mb-3' + elementClassAttribute: 'form-select xlarge' + elementErrorClassAttribute: ~ + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/Number.yaml b/Configuration/Form/Base/FormElements/Number.yaml new file mode 100644 index 0000000..b5dc79b --- /dev/null +++ b/Configuration/Form/Base/FormElements/Number.yaml @@ -0,0 +1,346 @@ +prototypes: + standard: + formElementsDefinition: + Number: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + propertyValidators: + 10: IntegerOrEmpty + 550: + identifier: step + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.step.label + propertyPath: properties.fluidAdditionalAttributes.step + propertyValidators: + 10: Integer + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 50: + value: 'postal-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.postal-code + 60: + value: 'bday-day' + label: formEditor.elements.FormElement.editor.autocomplete.option.bday-day + 70: + value: 'bday-month' + label: formEditor.elements.FormElement.editor.autocomplete.option.bday-month + 80: + value: 'bday-year' + label: formEditor.elements.FormElement.editor.autocomplete.option.bday-year + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 60: + value: Number + label: formEditor.elements.Number.editor.validators.Number.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + properties: + fluidAdditionalAttributes: + step: 1 + validators: + - + identifier: Number + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Number + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Number.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Number.label + description: formEditor.elements.Number.description + group: html5 + groupSorting: 400 + iconIdentifier: form-number + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-number mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + validators: + - + identifier: Number diff --git a/Configuration/Form/Base/FormElements/Page.yaml b/Configuration/Form/Base/FormElements/Page.yaml new file mode 100644 index 0000000..ed885c7 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Page.yaml @@ -0,0 +1,44 @@ +prototypes: + standard: + formElementsDefinition: + Page: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Page.editor.label.label + propertyPath: label + 300: + identifier: previousButtonLabel + templateName: Inspector-TextEditor + label: formEditor.elements.Page.editor.previousButtonLabel.label + propertyPath: renderingOptions.previousButtonLabel + 400: + identifier: nextButtonLabel + templateName: Inspector-TextEditor + label: formEditor.elements.Page.editor.nextButtonLabel.label + propertyPath: renderingOptions.nextButtonLabel + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + renderingOptions: + previousButtonLabel: formEditor.elements.Page.editor.previousButtonLabel.value + nextButtonLabel: formEditor.elements.Page.editor.nextButtonLabel.value + label: formEditor.elements.Page.label + description: formEditor.elements.Page.description + group: page + groupSorting: 100 + _isTopLevelFormElement: true + _isCompositeFormElement: true + iconIdentifier: form-page + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Page + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: true + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' diff --git a/Configuration/Form/Base/FormElements/Password.yaml b/Configuration/Form/Base/FormElements/Password.yaml new file mode 100644 index 0000000..d8857b6 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Password.yaml @@ -0,0 +1,337 @@ +prototypes: + standard: + formElementsDefinition: + Password: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'new-password' + label: formEditor.elements.FormElement.editor.autocomplete.option.new-password + 30: + value: 'current-password' + label: formEditor.elements.FormElement.editor.autocomplete.option.current-password + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Password.label + description: formEditor.elements.Password.description + group: input + groupSorting: 300 + iconIdentifier: form-password + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-password mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/RadioButton.yaml b/Configuration/Form/Base/FormElements/RadioButton.yaml new file mode 100644 index 0000000..677fea8 --- /dev/null +++ b/Configuration/Form/Base/FormElements/RadioButton.yaml @@ -0,0 +1,134 @@ +prototypes: + standard: + formElementsDefinition: + RadioButton: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + propertyValidators: + 10: NotEmpty + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 30: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 40: + value: 'tel-country-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-country-code + 50: + value: 'tel-area-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-area-code + 60: + value: 'sex' + label: formEditor.elements.FormElement.editor.autocomplete.option.sex + 70: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + label: formEditor.elements.RadioButton.label + description: formEditor.elements.RadioButton.description + group: select + groupSorting: 300 + iconIdentifier: form-radio-button + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + renderFieldset: 1 + fieldsetClassAttribute: 'form-element form-element-radio mb-3' + containerClassAttribute: 'form-check mb-2' + elementClassAttribute: form-check-input + elementErrorClassAttribute: ~ + labelClassAttribute: form-check-wrapping-label + labelTextClassAttribute: form-check-label + legendVisuallyHidden: 1 diff --git a/Configuration/Form/Base/FormElements/SingleSelect.yaml b/Configuration/Form/Base/FormElements/SingleSelect.yaml new file mode 100644 index 0000000..2a05eff --- /dev/null +++ b/Configuration/Form/Base/FormElements/SingleSelect.yaml @@ -0,0 +1,137 @@ +prototypes: + standard: + formElementsDefinition: + SingleSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + propertyValidators: + 10: NotEmpty + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 30: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 40: + value: 'tel-country-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-country-code + 50: + value: 'tel-area-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-area-code + 60: + value: 'sex' + label: formEditor.elements.FormElement.editor.autocomplete.option.sex + 70: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + label: formEditor.elements.SingleSelect.label + description: formEditor.elements.SingleSelect.description + group: select + groupSorting: 200 + iconIdentifier: form-single-select + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-select mb-3' + elementClassAttribute: form-select + elementErrorClassAttribute: ~ + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/StaticText.yaml b/Configuration/Form/Base/FormElements/StaticText.yaml new file mode 100644 index 0000000..6a06724 --- /dev/null +++ b/Configuration/Form/Base/FormElements/StaticText.yaml @@ -0,0 +1,75 @@ +prototypes: + standard: + formElementsDefinition: + StaticText: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.StaticText.editor.label.label + propertyPath: label + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 300: + identifier: staticText + templateName: Inspector-TextareaEditor + label: formEditor.elements.StaticText.editor.staticText.label + propertyPath: properties.text + enableRichtext: true + richtextConfiguration: form-content + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + text: '' + label: formEditor.elements.StaticText.label + description: formEditor.elements.StaticText.description + group: custom + groupSorting: 600 + iconIdentifier: form-static-text + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + text: '' + containerClassAttribute: 'form-element form-element-statictext mb-3' + variants: + - + identifier: hide-1 + renderingOptions: + enabled: false + condition: 'stepType == "SummaryPage" || finisherIdentifier in ["EmailToSender", "EmailToReceiver"]' diff --git a/Configuration/Form/Base/FormElements/SummaryPage.yaml b/Configuration/Form/Base/FormElements/SummaryPage.yaml new file mode 100644 index 0000000..856160a --- /dev/null +++ b/Configuration/Form/Base/FormElements/SummaryPage.yaml @@ -0,0 +1,48 @@ +prototypes: + standard: + formElementsDefinition: + SummaryPage: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.SummaryPage.editor.label.label + propertyPath: label + 300: + identifier: previousButtonLabel + templateName: Inspector-TextEditor + label: formEditor.elements.SummaryPage.editor.previousButtonLabel.label + propertyPath: renderingOptions.previousButtonLabel + 400: + identifier: nextButtonLabel + templateName: Inspector-TextEditor + label: formEditor.elements.SummaryPage.editor.nextButtonLabel.label + propertyPath: renderingOptions.nextButtonLabel + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + renderingOptions: + previousButtonLabel: formEditor.elements.SummaryPage.editor.previousButtonLabel.value + nextButtonLabel: formEditor.elements.SummaryPage.editor.nextButtonLabel.value + label: formEditor.elements.SummaryPage.label + description: formEditor.elements.SummaryPage.description + group: page + groupSorting: 200 + _isTopLevelFormElement: true + _isCompositeFormElement: false + iconIdentifier: form-summary-page + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Page + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + listClassAttribute: summary-list + listRowClassAttribute: row + labelWrapperClassAttribute: col + valueWrapperClassAttribute: col diff --git a/Configuration/Form/Base/FormElements/Telephone.yaml b/Configuration/Form/Base/FormElements/Telephone.yaml new file mode 100644 index 0000000..0d93b79 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Telephone.yaml @@ -0,0 +1,336 @@ +prototypes: + standard: + formElementsDefinition: + Telephone: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'tel' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel + 30: + value: 'tel-country-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-country-code + 40: + value: 'tel-national' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-national + 50: + value: 'tel-area-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-area-code + 60: + value: 'tel-local' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-local + 70: + value: 'tel-extension' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel-extension + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Telephone.label + description: formEditor.elements.Telephone.description + group: html5 + groupSorting: 200 + iconIdentifier: form-telephone + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-phone mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + validators: + - + identifier: RegularExpression + options: + regularExpression: '/^.*$/' diff --git a/Configuration/Form/Base/FormElements/Text.yaml b/Configuration/Form/Base/FormElements/Text.yaml new file mode 100644 index 0000000..264eb61 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Text.yaml @@ -0,0 +1,391 @@ +prototypes: + standard: + formElementsDefinition: + Text: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'name' + label: formEditor.elements.FormElement.editor.autocomplete.option.name + 30: + value: 'honorific-prefix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-prefix + 40: + value: 'given-name' + label: formEditor.elements.FormElement.editor.autocomplete.option.given-name + 50: + value: 'additional-name' + label: formEditor.elements.FormElement.editor.autocomplete.option.additional-name + 60: + value: 'family-name' + label: formEditor.elements.FormElement.editor.autocomplete.option.family-name + 70: + value: 'honorific-suffix' + label: formEditor.elements.FormElement.editor.autocomplete.option.honorific-suffix + 80: + value: 'nickname' + label: formEditor.elements.FormElement.editor.autocomplete.option.nickname + 90: + value: 'organization-title' + label: formEditor.elements.FormElement.editor.autocomplete.option.organization-title + 100: + value: 'username' + label: formEditor.elements.FormElement.editor.autocomplete.option.username + 110: + value: 'organization' + label: formEditor.elements.FormElement.editor.autocomplete.option.organization + 120: + value: 'address-line1' + label: formEditor.elements.FormElement.editor.autocomplete.option.address-line1 + 130: + value: 'address-line2' + label: formEditor.elements.FormElement.editor.autocomplete.option.address-line2 + 140: + value: 'address-level1' + label: formEditor.elements.FormElement.editor.autocomplete.option.address-level1 + 150: + value: 'address-level2' + label: formEditor.elements.FormElement.editor.autocomplete.option.address-level2 + 190: + value: 'country-name' + label: formEditor.elements.FormElement.editor.autocomplete.option.country-name + 200: + value: 'postal-code' + label: formEditor.elements.FormElement.editor.autocomplete.option.postal-code + 210: + value: 'tel' + label: formEditor.elements.FormElement.editor.autocomplete.option.tel + 220: + value: 'impp' + label: formEditor.elements.FormElement.editor.autocomplete.option.impp + 230: + value: 'sex' + label: formEditor.elements.FormElement.editor.autocomplete.option.sex + 240: + value: 'language' + label: formEditor.elements.FormElement.editor.autocomplete.option.language + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Text.label + description: formEditor.elements.Text.description + group: input + groupSorting: 100 + iconIdentifier: form-text + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-text mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/Textarea.yaml b/Configuration/Form/Base/FormElements/Textarea.yaml new file mode 100644 index 0000000..b39a780 --- /dev/null +++ b/Configuration/Form/Base/FormElements/Textarea.yaml @@ -0,0 +1,331 @@ +prototypes: + standard: + formElementsDefinition: + Textarea: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'street-address' + label: formEditor.elements.FormElement.editor.autocomplete.option.street-address + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Textarea.label + description: formEditor.elements.Textarea.description + group: input + groupSorting: 200 + iconIdentifier: form-textarea + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-textarea mb-3' + elementClassAttribute: 'form-control xxlarge' + elementErrorClassAttribute: error + labelClassAttribute: form-label diff --git a/Configuration/Form/Base/FormElements/Url.yaml b/Configuration/Form/Base/FormElements/Url.yaml new file mode 100644 index 0000000..2fa02aa --- /dev/null +++ b/Configuration/Form/Base/FormElements/Url.yaml @@ -0,0 +1,324 @@ +prototypes: + standard: + formElementsDefinition: + Url: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 240: + identifier: enabled + templateName: Inspector-CheckboxEditor + label: formEditor.elements.FormElement.editor.enabled.label + propertyPath: renderingOptions.enabled + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 600: + identifier: autocomplete + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FormElement.editor.autocomplete.label + propertyPath: properties.fluidAdditionalAttributes.autocomplete + doNotSetIfPropertyValueIsEmpty: true + selectOptions: + 10: + value: '' + label: formEditor.elements.FormElement.editor.autocomplete.option.none + 15: + value: 'off' + label: formEditor.elements.FormElement.editor.autocomplete.option.off + 20: + value: 'url' + label: formEditor.elements.FormElement.editor.autocomplete.option.url + 30: + value: 'impp' + label: formEditor.elements.FormElement.editor.autocomplete.option.impp + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1221551320 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Url.label + description: formEditor.elements.Url.description + group: html5 + groupSorting: 300 + iconIdentifier: form-url + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + properties: + containerClassAttribute: 'form-element form-element-url mb-3' + elementClassAttribute: form-control + elementErrorClassAttribute: ~ + labelClassAttribute: form-label + validators: + - + identifier: RegularExpression + options: + regularExpression: '/^.*$/' diff --git a/Configuration/Form/Base/Validators/Alphanumeric.yaml b/Configuration/Form/Base/Validators/Alphanumeric.yaml new file mode 100644 index 0000000..7f3c78e --- /dev/null +++ b/Configuration/Form/Base/Validators/Alphanumeric.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + Alphanumeric: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\AlphanumericValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label diff --git a/Configuration/Form/Base/Validators/Count.yaml b/Configuration/Form/Base/Validators/Count.yaml new file mode 100644 index 0000000..22cf2f6 --- /dev/null +++ b/Configuration/Form/Base/Validators/Count.yaml @@ -0,0 +1,17 @@ +prototypes: + standard: + validatorsDefinition: + Count: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\CountValidator + #options: + # minimum count to accept + #minimum: + # maximum count to accept + #maximum: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + predefinedDefaults: + options: + minimum: '' + maximum: '' diff --git a/Configuration/Form/Base/Validators/DateRange.yaml b/Configuration/Form/Base/Validators/DateRange.yaml new file mode 100644 index 0000000..4101eee --- /dev/null +++ b/Configuration/Form/Base/Validators/DateRange.yaml @@ -0,0 +1,18 @@ +prototypes: + standard: + validatorsDefinition: + DateRange: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\DateRangeValidator + options: + format: Y-m-d + # minimum date formatted as Y-m-d + #minimum: + # maximum date formatted as Y-m-d + #maximum: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.validators.DateRange.editor.header.label + predefinedDefaults: + options: + minimum: '' + maximum: '' diff --git a/Configuration/Form/Base/Validators/DateTime.yaml b/Configuration/Form/Base/Validators/DateTime.yaml new file mode 100644 index 0000000..0583950 --- /dev/null +++ b/Configuration/Form/Base/Validators/DateTime.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + DateTime: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\DateTimeValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.DatePicker.validators.DateTime.editor.header.label diff --git a/Configuration/Form/Base/Validators/EmailAddress.yaml b/Configuration/Form/Base/Validators/EmailAddress.yaml new file mode 100644 index 0000000..b5a92ef --- /dev/null +++ b/Configuration/Form/Base/Validators/EmailAddress.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + EmailAddress: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\EmailAddressValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label diff --git a/Configuration/Form/Base/Validators/FileSize.yaml b/Configuration/Form/Base/Validators/FileSize.yaml new file mode 100644 index 0000000..00fd35f --- /dev/null +++ b/Configuration/Form/Base/Validators/FileSize.yaml @@ -0,0 +1,17 @@ +prototypes: + standard: + validatorsDefinition: + FileSize: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\FileSizeValidator + #options: + # minimum file size to accept + #minimum: + # maximum file size to accept + #maximum: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + predefinedDefaults: + options: + minimum: 0B + maximum: 10M diff --git a/Configuration/Form/Base/Validators/Float.yaml b/Configuration/Form/Base/Validators/Float.yaml new file mode 100644 index 0000000..a387f7e --- /dev/null +++ b/Configuration/Form/Base/Validators/Float.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + Float: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\FloatValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Float.label diff --git a/Configuration/Form/Base/Validators/Integer.yaml b/Configuration/Form/Base/Validators/Integer.yaml new file mode 100644 index 0000000..537caf2 --- /dev/null +++ b/Configuration/Form/Base/Validators/Integer.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + Integer: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\IntegerValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Integer.label diff --git a/Configuration/Form/Base/Validators/NotEmpty.yaml b/Configuration/Form/Base/Validators/NotEmpty.yaml new file mode 100644 index 0000000..9ea36bd --- /dev/null +++ b/Configuration/Form/Base/Validators/NotEmpty.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + NotEmpty: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.editor.requiredValidator.label diff --git a/Configuration/Form/Base/Validators/Number.yaml b/Configuration/Form/Base/Validators/Number.yaml new file mode 100644 index 0000000..4535425 --- /dev/null +++ b/Configuration/Form/Base/Validators/Number.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + Number: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NumberValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Number.label diff --git a/Configuration/Form/Base/Validators/NumberRange.yaml b/Configuration/Form/Base/Validators/NumberRange.yaml new file mode 100644 index 0000000..d6a504b --- /dev/null +++ b/Configuration/Form/Base/Validators/NumberRange.yaml @@ -0,0 +1,17 @@ +prototypes: + standard: + validatorsDefinition: + NumberRange: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NumberRangeValidator + #options: + # minimum value to accept + #minimum: + # maximum value to accept + #maximum: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + predefinedDefaults: + options: + minimum: '' + maximum: '' diff --git a/Configuration/Form/Base/Validators/RegularExpression.yaml b/Configuration/Form/Base/Validators/RegularExpression.yaml new file mode 100644 index 0000000..0544ea9 --- /dev/null +++ b/Configuration/Form/Base/Validators/RegularExpression.yaml @@ -0,0 +1,14 @@ +prototypes: + standard: + validatorsDefinition: + RegularExpression: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\RegularExpressionValidator + #options: + # the regular expression to use for validation, used as given + #regularExpression: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.RegularExpression.label + predefinedDefaults: + options: + regularExpression: '' diff --git a/Configuration/Form/Base/Validators/StringLength.yaml b/Configuration/Form/Base/Validators/StringLength.yaml new file mode 100644 index 0000000..264317e --- /dev/null +++ b/Configuration/Form/Base/Validators/StringLength.yaml @@ -0,0 +1,17 @@ +prototypes: + standard: + validatorsDefinition: + StringLength: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\StringLengthValidator + #options: + # minimum length for a valid string + #minimum: + # maximum length for a valid string + #maximum: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + predefinedDefaults: + options: + minimum: '' + maximum: '' diff --git a/Configuration/Form/Base/Validators/Text.yaml b/Configuration/Form/Base/Validators/Text.yaml new file mode 100644 index 0000000..3d14b74 --- /dev/null +++ b/Configuration/Form/Base/Validators/Text.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + validatorsDefinition: + Text: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\TextValidator + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Text.label diff --git a/Configuration/Form/Base/config.yaml b/Configuration/Form/Base/config.yaml new file mode 100644 index 0000000..616674b --- /dev/null +++ b/Configuration/Form/Base/config.yaml @@ -0,0 +1,177 @@ +imports: + # Validators + - { resource: 'EXT:form/Configuration/Form/Base/Validators/NotEmpty.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/DateTime.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Alphanumeric.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Text.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/StringLength.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/EmailAddress.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Integer.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Float.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Number.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/NumberRange.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/RegularExpression.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/Count.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/FileSize.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Validators/DateRange.yaml' } + + # Form elements + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Form.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Page.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/SummaryPage.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Fieldset.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/GridColumn.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/GridRow.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Text.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Password.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/AdvancedPassword.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Textarea.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Honeypot.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Hidden.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Email.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Telephone.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Url.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Number.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Date.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Checkbox.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/MultiCheckbox.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/MultiSelect.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/RadioButton.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/SingleSelect.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/CountrySelect.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/StaticText.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/ContentElement.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/FileUpload.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/ImageUpload.yaml' } + + # Finishers + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/Closure.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/Confirmation.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/EmailToSender.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/EmailToReceiver.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/DeleteUploads.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/FlashMessage.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/Redirect.yaml' } + - { resource: 'EXT:form/Configuration/Form/Base/Finishers/SaveToDatabase.yaml' } + +name: typo3/form-base +label: 'TYPO3 Form — Base Configuration' +priority: 10 + +persistenceManager: + allowSaveToExtensionPaths: false + allowDeleteFromExtensionPaths: false + sortByKeys: + - name + - fileUid + sortAscending: true + +prototypes: + standard: + formEditor: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + dynamicJavaScriptModules: + app: '@typo3/form/backend/form-editor.js' + mediator: '@typo3/form/backend/form-editor/mediator.js' + viewModel: '@typo3/form/backend/form-editor/view-model.js' + addInlineSettings: { } + maximumUndoSteps: 10 + stylesheets: + 200: 'EXT:form/Resources/Public/Css/form.css' + formEditorFluidConfiguration: + templatePathAndFilename: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + + formEditorPartials: + Modal-InsertElements: Modals/InsertElements + Modal-InsertPages: Modals/InsertPages + Modal-ValidationErrors: Modals/ValidationErrors + Inspector-FormElementHeaderEditor: Inspector/FormElementHeaderEditor + Inspector-CollectionElementHeaderEditor: Inspector/CollectionElementHeaderEditor + Inspector-TextEditor: Inspector/TextEditor + Inspector-PropertyGridEditor: Inspector/PropertyGridEditor + Inspector-SingleSelectEditor: Inspector/SingleSelectEditor + Inspector-MultiSelectEditor: Inspector/MultiSelectEditor + Inspector-GridColumnViewPortConfigurationEditor: Inspector/GridColumnViewPortConfigurationEditor + Inspector-TextareaEditor: Inspector/TextareaEditor + Inspector-RemoveElementEditor: Inspector/RemoveElementEditor + Inspector-FinishersEditor: Inspector/FinishersEditor + Inspector-ValidatorsEditor: Inspector/ValidatorsEditor + Inspector-RequiredValidatorEditor: Inspector/RequiredValidatorEditor + Inspector-CheckboxEditor: Inspector/CheckboxEditor + Inspector-ValidationErrorMessageEditor: Inspector/ValidationErrorMessageEditor + Inspector-Typo3WinBrowserEditor: Inspector/Typo3WinBrowserEditor + Inspector-MaximumFileSizeEditor: Inspector/MaximumFileSizeEditor + Inspector-CountrySelectEditor: Inspector/CountrySelectEditor + Inspector-CountrySingleSelectEditor: Inspector/CountrySingleSelectEditor + Inspector-DateEditor: Inspector/DateEditor + + formElementPropertyValidatorsDefinition: + NotEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NotEmpty.label + Integer: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.Integer.label + NaiveEmail: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + NaiveEmailOrEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + FormElementIdentifierWithinCurlyBracesInclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FormElementIdentifierWithinCurlyBracesExclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FileSize: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FileSize.label + RFC3339FullDate: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RFC3339FullDate.label + RegularExpressionPattern: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RegularExpressionPattern.label + ItemCount: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.ItemCount.label + IntegerList: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.IntegerList.label + + formElementGroups: + input: + label: formEditor.formElementGroups.input.label + html5: + label: formEditor.formElementGroups.html5.label + select: + label: formEditor.formElementGroups.select.label + custom: + label: formEditor.formElementGroups.custom.label + container: + label: formEditor.formElementGroups.container.label + page: + label: formEditor.formElementGroups.page.label + + formEngine: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + +formManager: + dynamicJavaScriptModules: + app: '@typo3/form/backend/form-manager.js' + viewModel: '@typo3/form/backend/form-manager/view-model.js' + stylesheets: + 100: 'EXT:form/Resources/Public/Css/form.css' + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + selectablePrototypesConfiguration: + 100: + identifier: standard + label: formManager.selectablePrototypesConfiguration.standard.label + newFormTemplates: + 100: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.blankForm.label + 200: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.simpleContactForm.label + controller: + deleteAction: + errorTitle: formManagerController.deleteAction.error.title + errorMessage: formManagerController.deleteAction.error.body diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php new file mode 100644 index 0000000..aa8b6a4 --- /dev/null +++ b/Configuration/JavaScriptModules.php @@ -0,0 +1,11 @@ + [ + 'backend', + 'core', + ], + 'imports' => [ + '@typo3/form/backend/' => 'EXT:form/Resources/Public/JavaScript/backend/', + ], +]; diff --git a/Configuration/RTE/FormContent.yaml b/Configuration/RTE/FormContent.yaml new file mode 100644 index 0000000..51c306c --- /dev/null +++ b/Configuration/RTE/FormContent.yaml @@ -0,0 +1,23 @@ +# Load processing options +imports: + - { resource: 'EXT:form/Configuration/RTE/ProcessingContent.yaml' } + - { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml' } + - { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Plugins.yaml' } + +# RTE configuration for form content fields (e.g., StaticText) +# Contains extended formatting options including lists +editor: + config: + toolbar: + items: + - bold + - italic + - '|' + - link + - '|' + - bulletedList + - numberedList + - '|' + - clipboard + - undo + - redo diff --git a/Configuration/RTE/FormLabel.yaml b/Configuration/RTE/FormLabel.yaml new file mode 100644 index 0000000..2f6ede2 --- /dev/null +++ b/Configuration/RTE/FormLabel.yaml @@ -0,0 +1,20 @@ +# Load processing options +imports: + - { resource: 'EXT:form/Configuration/RTE/ProcessingLabel.yaml' } + - { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Base.yaml' } + - { resource: 'EXT:rte_ckeditor/Configuration/RTE/Editor/Plugins.yaml' } + +# RTE configuration for form labels and short text fields +# Contains only essential formatting options: bold, italic, link +editor: + config: + toolbar: + items: + - bold + - italic + - '|' + - link + - '|' + - clipboard + - undo + - redo diff --git a/Configuration/RTE/ProcessingContent.yaml b/Configuration/RTE/ProcessingContent.yaml new file mode 100644 index 0000000..7f93e0c --- /dev/null +++ b/Configuration/RTE/ProcessingContent.yaml @@ -0,0 +1,40 @@ +# ******************************************************** +# Processing configuration for form content fields +# Extended version that allows lists +# https://docs.typo3.org/permalink/t3tsref:rte-config-proc +# ******************************************************** + +processing: + mode: default + # Tags that are allowed in the content + # Includes list elements for extended formatting + allowTags: + - a + - br + - i + - strong + - ul + - ol + - li + - p + + denyTags: b,u,img,div,center,pre,figure,figcaption,font,hr,sub,sup,em,blockquote,strike,span,abbr,acronym,dfn + + ## Tags that are allowed outside of paragraphs + allowTagsOutside: + - ul + - ol + + ## CONTENT TO PERSISTENCE + HTMLparser_db: + + ## REMOVE OPEN OFFICE META DATA TAGS, WORD 2003 TAGS, LINK, META, STYLE AND TITLE TAGS, AND DEPRECATED HTML TAGS + removeTags: [link, meta, o:p, sdfield, style, title, font, center] + + ## PROTECT CUSTOM TAGS + keepNonMatchedTags: protect + + # HTML Sanitizer + htmlSanitize: + build: default + diff --git a/Configuration/RTE/ProcessingLabel.yaml b/Configuration/RTE/ProcessingLabel.yaml new file mode 100644 index 0000000..f1621d6 --- /dev/null +++ b/Configuration/RTE/ProcessingLabel.yaml @@ -0,0 +1,37 @@ +# ******************************************************** +# Sets the proc options for all default configurations +# https://docs.typo3.org/permalink/t3tsref:rte-config-proc +# ******************************************************** + +processing: + mode: default + # Tags that are allowed in the content in general + # If you adapt this preset, you need to ship your own Checkbox.fluid.html template alongside it + # and adapt the `stripTags` call + allowTags: + - a + - br + - i + - strong + + denyTags: b,u,img,div,center,pre,figure,figcaption,font,hr,sub,sup,em,li,ul,ol,blockquote,strike,span,abbr,acronym,dfn + + ## Tags that are allowed outside of paragraphs + allowTagsOutside: [] + + ## CONTENT TO PERSISTENCE + HTMLparser_db: + + ## REMOVE OPEN OFFICE META DATA TAGS, WORD 2003 TAGS, LINK, META, STYLE AND TITLE TAGS, AND DEPRECATED HTML TAGS + ## We use this rule instead of the denyTags rule so that we can protect custom tags without protecting these unwanted tags. + removeTags: [link, meta, o:p, sdfield, style, title, font, center] + + ## PROTECT CUSTOM TAGS + keepNonMatchedTags: protect + + # HTML Sanitizer + # `htmlSanitize = false | null` to disable individually + htmlSanitize: + # either preset name as declared in `$GLOBALS['TYPO3_CONF_VARS']['SYS']['htmlSanitizer']` + # or class-name implementing interface `\TYPO3\HtmlSanitizer\Builder\BuilderInterface` + build: default diff --git a/Configuration/Services.php b/Configuration/Services.php new file mode 100644 index 0000000..3911364 --- /dev/null +++ b/Configuration/Services.php @@ -0,0 +1,30 @@ +registerForAutoconfiguration(FinisherInterface::class)->addTag('form.finisher'); + $containerBuilder->addCompilerPass(new PublicServicePass('form.finisher', true)); + + if ($containerBuilder->hasDefinition(ProviderRegistry::class)) { + $container->services()->defaults()->autowire()->autoconfigure()->public() + ->set('lowlevel.configuration.module.provider.formyamlconfiguration') + ->class(FormYamlProvider::class) + ->tag( + 'lowlevel.configuration.module.provider', + [ + 'identifier' => 'formYamlConfiguration', + 'after' => 'eventListeners', + ] + ); + } +}; diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000..afa0857 --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,40 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + TYPO3\CMS\Form\: + resource: '../Classes/*' + exclude: + - '../Classes/{Domain/Model}' + - '../Classes/Mvc/Configuration/FormYamlConfiguration.php' + + # Explicitly declared public so that ConfigurationManager can receive it via + # DI autowiring. Populated at container build time via FormYamlCollectorConfigurator. + TYPO3\CMS\Form\Mvc\Configuration\FormYamlCollector: + public: true + configurator: + - '@TYPO3\CMS\Form\DependencyInjection\FormYamlCollectorConfigurator' + - 'configure' + + TYPO3\CMS\Form\SoftReference\FormPersistenceIdentifierSoftReferenceParser: + tags: + - name: softreference.parser + parserKey: formPersistenceIdentifier + + TYPO3\CMS\Form\Mvc\Property\TypeConverter\FormDefinitionArrayConverter: + tags: + - name: extbase.type_converter + priority: 10 + target: TYPO3\CMS\Form\Type\FormDefinitionArray + sources: string + + TYPO3\CMS\Form\Storage\StorageAdapterFactory: + public: true + arguments: + $adapters: !tagged_iterator form.storage.adapter + + _instanceof: + TYPO3\CMS\Form\Storage\StorageAdapterInterface: + tags: [ 'form.storage.adapter' ] diff --git a/Configuration/Sets/Form/config.yaml b/Configuration/Sets/Form/config.yaml new file mode 100644 index 0000000..24216c7 --- /dev/null +++ b/Configuration/Sets/Form/config.yaml @@ -0,0 +1,2 @@ +name: typo3/form +label: Form Framework diff --git a/Configuration/Sets/Form/labels.xlf b/Configuration/Sets/Form/labels.xlf new file mode 100644 index 0000000..859aef8 --- /dev/null +++ b/Configuration/Sets/Form/labels.xlf @@ -0,0 +1,44 @@ + + + +
+ + + Form + + + Form + + + Templates + + + Translation + + + Path of Fluid Templates for form elements + + + Override the default Fluid template path for all form element rendering (e.g. EXT:my_sitepackage/Resources/Private/Templates/Form/Frontend/) + + + Path of Fluid Partials for form elements + + + Override the default Fluid partial path for all form element rendering (e.g. EXT:my_sitepackage/Resources/Private/Partials/Form/Frontend/) + + + Path of Fluid Layouts for form elements + + + Override the default Fluid layout path for all form element rendering (e.g. EXT:my_sitepackage/Resources/Private/Layouts/Form/Frontend/) + + + Additional translation file for form elements + + + Additional XLF translation file for form element labels (e.g. EXT:my_sitepackage/Resources/Private/Language/Form/locallang.xlf) + + + + diff --git a/Configuration/Sets/Form/settings.definitions.yaml b/Configuration/Sets/Form/settings.definitions.yaml new file mode 100644 index 0000000..2e8c0a2 --- /dev/null +++ b/Configuration/Sets/Form/settings.definitions.yaml @@ -0,0 +1,24 @@ +categories: + form: ~ + form.templates: + parent: form + form.translation: + parent: form + +settings: + form.templates.templateRootPath: + default: '' + type: string + category: form.templates + form.templates.partialRootPath: + default: '' + type: string + category: form.templates + form.templates.layoutRootPath: + default: '' + type: string + category: form.templates + form.translation.translationFile: + default: '' + type: string + category: form.translation diff --git a/Configuration/Sets/Form/setup.typoscript b/Configuration/Sets/Form/setup.typoscript new file mode 100644 index 0000000..c641d6d --- /dev/null +++ b/Configuration/Sets/Form/setup.typoscript @@ -0,0 +1 @@ +@import 'EXT:form/Configuration/TypoScript/setup.typoscript' diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php new file mode 100644 index 0000000..7292bbc --- /dev/null +++ b/Configuration/TCA/Overrides/sys_template.php @@ -0,0 +1,11 @@ + [ + 'title' => 'form.db:form_definition', + 'label' => 'label', + 'crdate' => 'crdate', + 'tstamp' => 'tstamp', + 'versioningWS' => false, + 'default_sortby' => 'label', + 'delete' => 'deleted', + 'rootLevel' => 1, + 'security' => [ + 'ignoreRootLevelRestriction' => true, + ], + 'typeicon_classes' => [ + 'default' => 'content-form', + ], + ], + 'types' => [ + '0' => [ + 'showitem' => ' + --div--;core.form.tabs:general, label, identifier, configuration, + ', + ], + ], + 'columns' => [ + 'label' => [ + 'label' => 'form.db:form_definition.label', + 'config' => [ + 'type' => 'input', + 'size' => 50, + 'eval' => 'trim', + 'readOnly' => true, + 'required' => true, + ], + ], + 'identifier' => [ + 'label' => 'form.db:form_definition.identifier', + 'config' => [ + 'type' => 'input', + 'size' => 50, + 'eval' => 'trim,unique', + 'readOnly' => true, + 'required' => true, + ], + ], + 'configuration' => [ + 'label' => 'form.db:form_definition.configuration', + 'config' => [ + 'type' => 'json', + 'readOnly' => true, + 'required' => true, + ], + ], + ], + +]; diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript new file mode 100644 index 0000000..b4b60af --- /dev/null +++ b/Configuration/TypoScript/setup.typoscript @@ -0,0 +1,28 @@ +plugin.tx_form { + view { + templateRootPaths { + 0 = EXT:form/Resources/Private/Frontend/Templates/ + 10 = {$form.templates.templateRootPath} + } + partialRootPaths { + 0 = EXT:form/Resources/Private/Frontend/Partials/ + 10 = {$form.templates.partialRootPath} + } + layoutRootPaths { + 0 = EXT:form/Resources/Private/Frontend/Layouts/ + 10 = {$form.templates.layoutRootPath} + } + } + + mvc { + callDefaultActionIfActionCantBeResolved = 1 + } +} + +# Rendering of content elements +lib.tx_form.contentElementRendering = RECORDS +lib.tx_form.contentElementRendering { + tables = tt_content + source.current = 1 + dontCheckPid = 1 +} diff --git a/Configuration/page.tsconfig b/Configuration/page.tsconfig new file mode 100644 index 0000000..0c38344 --- /dev/null +++ b/Configuration/page.tsconfig @@ -0,0 +1,4 @@ +# Deny creating form_definition records via the "New Record" wizard +# or the "+" button in the record list. Form definitions should only +# be created through the Form Manager module. +mod.web_list.deniedNewTables := addToList(form_definition) diff --git a/Documentation/D/Events/Index.rst b/Documentation/D/Events/Index.rst new file mode 100644 index 0000000..97c3f6f --- /dev/null +++ b/Documentation/D/Events/Index.rst @@ -0,0 +1,171 @@ +.. include:: /Includes.rst.txt + +.. _apireference-events: +.. _apireference-formeditor-events: +.. _apireference-formeditor-hooks-beforeformcreate: +.. _apireference-formeditor-hooks-beforeformcreate-connect: +.. _apireference-formeditor-hooks-beforeformcreate-use: +.. _apireference-formeditor-events-beforeformiscreatedevent: +.. _apireference-formeditor-hooks-beforeformduplicate: +.. _apireference-formeditor-hooks-beforeformduplicate-connect: +.. _apireference-formeditor-hooks-beforeformduplicate-use: +.. _apireference-formeditor-hooks-beforeformdelete: +.. _apireference-formeditor-hooks-beforeformdelete-connect: +.. _apireference-formeditor-hooks-beforeformdelete-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks: +.. _apireference-frontendrendering-runtimemanipulation-hooks-initializeformelement: +.. _apireference-frontendrendering-runtimemanipulation-hooks-initializeformelement-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-initializeformelement-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforeremovefromparentrenderable: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforeremovefromparentrenderable-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforeremovefromparentrenderable-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterbuildingfinished: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterbuildingfinished-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterbuildingfinished-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterinitializecurrentpage: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterinitializecurrentpage-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-afterinitializecurrentpage-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks-aftersubmit: +.. _apireference-frontendrendering-runtimemanipulation-hooks-aftersubmit-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-aftersubmit-use: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforerendering: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforerendering-connect: +.. _apireference-frontendrendering-runtimemanipulation-hooks-beforerendering-use: +.. _apireference-events-legacy-hooks-buildformvalidationconfiguration: +.. _apireference-events-legacy-hooks-afterformstateinitialized: +.. _apireference-events-legacy-hooks: + +================ +PSR-14 Events +================ + +EXT:form dispatches PSR-14 events at key points in the lifecycle of a form – +both in the backend form editor and during frontend rendering. These events +are the recommended extension point for developers; the legacy +:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']` hooks have been removed. + +.. seealso:: + The canonical, always-up-to-date reference for all EXT:form events lives + in the TYPO3 Core API documentation: + + `Form `_ + + The extension documentation below provides context, usage notes and + quick navigation; it intentionally avoids duplicating the full API + reference. + +.. contents:: + :depth: 1 + :local: + +.. _apireference-events-backend: + +Backend events (form editor / manager) +======================================= + +These events are dispatched when an editor creates, saves, duplicates or +deletes a form definition in the TYPO3 backend. + +.. _apireference-events-backend-table: + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Event + - When / what can be modified + * - `BeforeFormIsCreatedEvent + `_ + - Modify the form definition array and/or the persistence identifier + before a new form is created in the backend. + * - `BeforeFormIsSavedEvent + `_ + - Modify the form definition array and/or the persistence identifier + before a form is saved in the backend. + * - `BeforeFormIsDuplicatedEvent + `_ + - Modify the form definition array and/or the persistence identifier + of the copy before a form is duplicated. + * - `BeforeFormIsDeletedEvent + `_ + - Dispatched before a form is deleted. Set + :php:`$event->preventDeletion = true` to abort the deletion (the + event implements :php:`StoppableEventInterface`). + +.. _apireference-events-frontend: + +Frontend events (form rendering / runtime) +========================================== + +These events are dispatched during form rendering in the frontend. + +.. _apireference-events-frontend-table: + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Event + - When / what can be modified + * - `AfterFormIsBuiltEvent + `_ + - Modify the :php:`FormDefinition` object after the form factory has + finished building the complete form. + * - `BeforeRenderableIsAddedToFormEvent + `_ + - Modify or replace a renderable (page, section or element) before it + is added to the form tree. + * - `BeforeRenderableIsRemovedFromFormEvent + `_ + - Dispatched before a renderable is removed from the form tree. Set + :php:`$event->preventRemoval = true` to abort the removal (the + event implements :php:`StoppableEventInterface`). + * - `AfterCurrentPageIsResolvedEvent + `_ + - Override :php:`$event->currentPage` after the current page has been + resolved from the request, e.g. to implement conditional page-skip + logic. + * - `BeforeRenderableIsValidatedEvent + `_ + - Modify :php:`$event->value` before property-mapping and validation + run for each submitted form element. + * - `BeforeRenderableIsRenderedEvent + `_ + - Modify the renderable or the :php:`FormRuntime` just before a + renderable is output to the browser. + * - `BeforeEmailFinisherInitializedEvent + `_ + - Modify the options used by the :php:`EmailFinisher` (e.g. recipients, + subject) before they are applied. + * - `AfterFormStateInitializedEvent + `_ + - Enrich components with runtime data after the :php:`FormState` has + been restored from the request (form state and form session are + both available at this point). + * - `AfterFormDefinitionLoadedEvent + `_ + - Dispatched by :php:`FormPersistenceManager` after a YAML form + definition has been loaded from disk. Modify the definition globally + before it reaches the form factory. + * - `AfterFormDefinitionValidationConfigurationIsBuiltEvent + `_ + - Dispatched after the form definition validation configuration has + been built from the form editor setup. Add additional writable + property paths for custom inspector editor implementations. + +.. _apireference-events-register: + +Registering an event listener +============================== + +Register a listener via the :php:`#[AsEventListener]` PHP attribute: + +.. literalinclude:: _codesnippets/_MyFormEventListener.php + :language: php + :caption: EXT:my_extension/Classes/EventListener/MyFormEventListener.php + + +.. seealso:: + :ref:`t3coreapi:EventDispatcher` – TYPO3 Core API documentation on how to + register and implement PSR-14 event listeners. + diff --git a/Documentation/D/Events/_codesnippets/_MyFormEventListener.php b/Documentation/D/Events/_codesnippets/_MyFormEventListener.php new file mode 100644 index 0000000..e489538 --- /dev/null +++ b/Documentation/D/Events/_codesnippets/_MyFormEventListener.php @@ -0,0 +1,20 @@ +form['renderingOptions']['myCustomOption'] = 'value'; + } +} diff --git a/Documentation/D/FormEditor/FormElementModel/Index.rst b/Documentation/D/FormEditor/FormElementModel/Index.rst new file mode 100644 index 0000000..6123355 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/Index.rst @@ -0,0 +1,182 @@ +.. include:: /Includes.rst.txt + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel: +.. _apireference-formeditor-formelementmodel: + +================== +FormElement model +================== + +Every form element in the editor is represented by a **FormElement model** +object. This model is the single source of truth for all element properties +during an editing session; it is separate from the YAML form definition on +disk (which is only written on save). + +.. contents:: + :depth: 1 + :local: + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-property-identifierpath: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-property-parentrenderable: +.. _apireference-formeditor-formelementmodel-structure: + +Model structure +=============== + +A FormElement model carries all YAML properties of the element plus two +internal bookkeeping properties: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Property + - Description + * - :js:`__identifierPath` + - Slash-separated path from the root element to this element + (e.g. :js:`'example-form/page-1/name'`). Used as a unique key + for API lookups. + * - :js:`__parentRenderable` + - Reference to the parent FormElement model (filtered for display). + +Example model in memory: + +.. literalinclude:: _codesnippets/_model-structure.js + :language: javascript + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-get: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-get-propertycollectionproperties: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-get-renderables: +.. _apireference-formeditor-formelementmodel-api-get: + +get() +----- + +Reads a property by its dot-separated path. All intermediate levels must +be objects. + +.. literalinclude:: _codesnippets/_get-simple.js + :language: javascript + +For **property collections** (validators / finishers), whose position in +the array is unknown, use :js:`buildPropertyPath()` first: + +.. literalinclude:: _codesnippets/_get-property-collection.js + :language: javascript + +For **renderables** (child elements), :js:`get('renderables')` returns a +plain array of FormElement models. To access a specific child, use +:js:`formEditorApp.getFormElementByIdentifierPath()` with the full path. + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-set: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-set-propertycollectionproperties: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-set-renderables: +.. _apireference-formeditor-formelementmodel-api-set: + +set() +----- + +Writes a property by its dot-separated path. Every :js:`set()` call +automatically publishes all events registered for that path via +:ref:`on() `, including +the built-in +:ref:`core/formElement/somePropertyChanged `. + +.. literalinclude:: _codesnippets/_set.js + :language: javascript + +To modify property collection properties or add child renderables, use +the dedicated API methods on :js:`formEditorApp` / :js:`getViewModel()` +instead of setting array positions directly: + +- :js:`createAndAddFormElement()` +- :js:`addFormElement()` +- :js:`moveFormElement()` +- :js:`removeFormElement()` + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-unset: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-unset-propertycollectionproperties: +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-unset-renderables: +.. _apireference-formeditor-formelementmodel-api-unset: + +unset() +------- + +Removes a property at the given dot-separated path. + +.. literalinclude:: _codesnippets/_unset.js + :language: javascript + +For property collection properties, use :js:`buildPropertyPath()` in the +same way as for :ref:`get() `. + +To remove a child renderable, call +:js:`formEditorApp.removeFormElement()`. + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-on: +.. _apireference-formeditor-formelementmodel-api-on: + +on() +---- + +Registers an additional publish/subscribe event name that is fired +whenever :js:`set()` is called for a given property path. + +.. literalinclude:: _codesnippets/_on.js + :language: javascript + +By default EXT:form registers +:ref:`core/formElement/somePropertyChanged ` +for every known property path of every form element. + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-off: +.. _apireference-formeditor-formelementmodel-api-off: + +off() +----- + +Removes an event registration created with :js:`on()`. + +.. literalinclude:: _codesnippets/_off.js + :language: javascript + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-getobjectdata: +.. _apireference-formeditor-formelementmodel-api-getobjectdata: + +getObjectData() +--------------- + +Returns a deep-cloned plain object of all properties. Used internally for +Ajax serialisation. Provides read access to data set via :js:`set()` from +outside the model without breaking encapsulation. + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-clone: +.. _apireference-formeditor-formelementmodel-api-clone: + +clone() +------- + +Returns a fully dereferenced clone of the FormElement model. + +.. literalinclude:: _codesnippets/_clone.js + :language: javascript + + +.. _apireference-formeditor-basicjavascriptconcepts-formelementmodel-method-tostring: +.. _apireference-formeditor-formelementmodel-api-tostring: + +toString() +---------- + +Returns the model data as a JSON string. Intended for debugging. + +.. literalinclude:: _codesnippets/_to-string.js + :language: javascript diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_clone.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_clone.js new file mode 100644 index 0000000..6fc0515 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_clone.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + const formElement = formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name'); + const copy = formElement.clone(); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-property-collection.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-property-collection.js new file mode 100644 index 0000000..5eb188e --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-property-collection.js @@ -0,0 +1,10 @@ +export function bootstrap(formEditorApp) { + const formElement = formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name'); + + const propertyPath = formEditorApp + .buildPropertyPath('options.minimum', 'StringLength', 'validators', formElement); + // propertyPath = e.g. 'validators.0.options.minimum' + + const value = formElement.get(propertyPath); // '1' +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-simple.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-simple.js new file mode 100644 index 0000000..59b5a82 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_get-simple.js @@ -0,0 +1,6 @@ +export function bootstrap(formEditorApp) { + // Returns 'Name' + const placeholder = formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name') + .get('properties.fluidAdditionalAttributes.placeholder'); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_model-structure.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_model-structure.js new file mode 100644 index 0000000..1ef3513 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_model-structure.js @@ -0,0 +1,19 @@ +// Illustrative snapshot of a FormElement model as it exists in memory at runtime. +// The actual object is managed by the FormElement class – access it via +// formEditorApp.getFormElementByIdentifierPath() and the get()/set() API. +export const formElementSnapshot = { + identifier: 'name', + defaultValue: '', + label: 'Name', + type: 'Text', + properties: { + fluidAdditionalAttributes: { + placeholder: 'Name', + }, + }, + __parentRenderable: 'example-form/page-1 (filtered)', + __identifierPath: 'example-form/page-1/name', + validators: [ + { identifier: 'NotEmpty' }, + ], +}; diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_off.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_off.js new file mode 100644 index 0000000..a3e827a --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_off.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name') + .off('properties.fluidAdditionalAttributes.placeholder', 'my/custom/event'); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_on.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_on.js new file mode 100644 index 0000000..353c896 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_on.js @@ -0,0 +1,9 @@ +export function bootstrap(formEditorApp) { + const element = formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name'); + + element.on('properties.fluidAdditionalAttributes.placeholder', 'my/custom/event'); + + // The next set() on that path will also publish 'my/custom/event'. + element.set('properties.fluidAdditionalAttributes.placeholder', 'New Placeholder'); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_set.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_set.js new file mode 100644 index 0000000..f8d3964 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_set.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name') + .set('properties.fluidAdditionalAttributes.placeholder', 'New Placeholder'); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_to-string.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_to-string.js new file mode 100644 index 0000000..742e5d8 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_to-string.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + const formElement = formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name'); + console.log(formElement.toString()); +} diff --git a/Documentation/D/FormEditor/FormElementModel/_codesnippets/_unset.js b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_unset.js new file mode 100644 index 0000000..64cd795 --- /dev/null +++ b/Documentation/D/FormEditor/FormElementModel/_codesnippets/_unset.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + formEditorApp + .getFormElementByIdentifierPath('example-form/page-1/name') + .unset('properties.fluidAdditionalAttributes.placeholder'); +} diff --git a/Documentation/D/FormEditor/Index.rst b/Documentation/D/FormEditor/Index.rst new file mode 100644 index 0000000..c6c4b94 --- /dev/null +++ b/Documentation/D/FormEditor/Index.rst @@ -0,0 +1,97 @@ +.. include:: /Includes.rst.txt + + +.. _apireference-formeditor: +.. _apireference-formeditor-basicjavascriptconcepts: +.. _apireference-formeditor-basicjavascriptconcepts-events: +.. _apireference-formeditor-stage: + +=========== +Form Editor +=========== + +This chapter is the developer reference for the TYPO3 backend form editor. +It covers the JavaScript extension points and the data model used by the +editor's TypeScript modules. + +.. contents:: + :depth: 1 + :local: + +.. _apireference-formeditor-architecture: + +Architecture overview +===================== + +The form editor consists of four cooperating TypeScript modules, each +responsible for one UI component: + +.. list-table:: + :header-rows: 1 + :widths: 30 35 35 + + * - Module (import path) + - Component + - Responsibility + * - :js:`@typo3/form/backend/form-editor/view-model` + - — + - Central view model; wires DOM events and publishes/subscribes + to all cross-component events. + * - :js:`@typo3/form/backend/form-editor/stage-component` + - **Stage** + - Renders the abstract and preview views of the current form page. + * - :js:`@typo3/form/backend/form-editor/inspector-component` + - **Inspector** + - Renders the property editors for the selected form element. + * - :js:`@typo3/form/backend/form-editor/tree-component-adapter` + - **Structure tree** + - Wraps the TYPO3 backend tree web component and bridges its + events to the publish/subscribe bus. + * - :js:`@typo3/form/backend/form-editor/mediator` + - — + - Wires all publish/subscribe events to view-model actions. + Loaded automatically; replace via + :yaml:`dynamicJavaScriptModules.mediator` only when you need to + completely swap the event-wiring logic. + +All modules communicate exclusively via a **publish/subscribe bus** +(:js:`PublisherSubscriber`). Direct module-to-module calls are avoided +so that extension code can hook into any point without modifying core +files. + +.. _apireference-formeditor-custom-modules: + +Registering a custom JavaScript module +======================================= + +Custom modules must export a :js:`bootstrap` function. The form editor +calls this function once all built-in modules have loaded, passing the +central :js:`FormEditor` application object as the sole argument. + +.. rst-class:: bignums-xxl + +1. Create the JavaScript module + + .. literalinclude:: _codesnippets/_bootstrap.js + :language: javascript + :caption: EXT:my_extension/Resources/Public/JavaScript/backend/form-editor/view-model.js + +2. Register the module in the importmap + + .. literalinclude:: _codesnippets/_JavaScriptModules.php + :language: php + :caption: EXT:my_extension/Configuration/JavaScriptModules.php + +3. Tell the form editor to load the module + + .. literalinclude:: _codesnippets/_prototype-setup.yaml + :language: yaml + :caption: EXT:my_extension/Configuration/Form/MyFormSet/config.yaml + + +.. toctree:: + :maxdepth: 1 + + JavaScriptEvents/Index + StageTemplates/Index + FormElementModel/Index diff --git a/Documentation/D/FormEditor/JavaScriptEvents/Index.rst b/Documentation/D/FormEditor/JavaScriptEvents/Index.rst new file mode 100644 index 0000000..1b4ccd1 --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/Index.rst @@ -0,0 +1,1717 @@ +.. include:: /Includes.rst.txt + +.. _apireference-formeditor-jsevents: + +=================== +JavaScript events +=================== + +The form editor uses a **publish/subscribe bus** for all cross-component +communication. Any custom JavaScript module can subscribe to these events +to extend or react to editor behaviour without patching core files. + +.. note:: + The module system is **ES modules** (ESM). The legacy AMD + :js:`define([…], function() {})` pattern from TYPO3 v11 and earlier is + no longer supported. Custom modules must use :js:`export function bootstrap(formEditorApp)`. + See :ref:`apireference-formeditor-custom-modules`. + +.. contents:: + :depth: 1 + :local: + + +.. _apireference-formeditor-jsevents-pubsub: + +Publish / subscribe basics +========================== + +.. literalinclude:: _codesnippets/_subscribe.js + :language: javascript + :caption: Subscribe to an event + +.. literalinclude:: _codesnippets/_publish.js + :language: javascript + :caption: Publish a custom event from within your module + + +.. note:: + The order in which subscribers receive an event is not guaranteed. + Subscribers cannot pass data to each other. All event handlers must + be designed without assumptions about execution order. + + +.. _apireference-formeditor-jsevents-overview: + +Event quick-reference +===================== + +.. _apireference-formeditor-jsevents-overview-lifecycle: + +Lifecycle +--------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/ready ` + - All modules loaded; editor is fully initialised. + + +.. _apireference-formeditor-jsevents-overview-ajax: + +Ajax / data transfer +-------------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`core/ajax/saveFormDefinition/success ` + - Form definition saved successfully. + * - :ref:`core/ajax/saveFormDefinition/error ` + - Server returned an error while saving. + * - :ref:`core/ajax/renderFormDefinitionPage/success ` + - Preview HTML for the current page returned successfully. + * - :ref:`core/ajax/error ` + - Any Ajax request (save or preview render) failed. + + +.. _apireference-formeditor-jsevents-overview-state: + +Application state +----------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`core/applicationState/add ` + - Undo/redo stack was updated. + * - :ref:`core/currentlySelectedFormElementChanged ` + - The currently selected form element changed. + * - :ref:`core/formElement/somePropertyChanged ` + - A property was written to a FormElement model via ``set()``. + + +.. _apireference-formeditor-jsevents-overview-formelement: + +Form element lifecycle +---------------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/formElement/inserted ` + - A new form element was added to the tree. + * - :ref:`view/formElement/moved ` + - A form element was moved within the tree. + * - :ref:`view/formElement/removed ` + - A form element was deleted. + + +.. _apireference-formeditor-jsevents-overview-collection: + +Collection elements (validators / finishers) +-------------------------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/collectionElement/new/added ` + - A validator or finisher was added. + * - :ref:`view/collectionElement/moved ` + - A validator or finisher was reordered. + * - :ref:`view/collectionElement/removed ` + - A validator or finisher was removed. + + +.. _apireference-formeditor-jsevents-overview-insert: + +Insert element / page dialogs +------------------------------ + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/insertElements/perform/before ` + - Insert new element *before* the selected one. + * - :ref:`view/insertElements/perform/after ` + - Insert new element *after* the selected one. + * - :ref:`view/insertElements/perform/inside ` + - Insert new element *inside* the selected composite. + * - :ref:`view/insertElements/perform/bottom ` + - Insert new element at the end of the current page. + * - :ref:`view/insertPages/perform ` + - Insert a new page after the current one. + + +.. _apireference-formeditor-jsevents-overview-header: + +Header buttons +-------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/header/button/save/clicked ` + - "Save" button clicked. + * - :ref:`view/header/button/close/clicked ` + - "Close" button clicked (with unsaved changes guard). + * - :ref:`view/header/button/newPage/clicked ` + - "New page" button clicked. + * - :ref:`view/header/formSettings/clicked ` + - "Form settings" button clicked. + * - :ref:`view/undoButton/clicked ` + - Undo button clicked. + * - :ref:`view/redoButton/clicked ` + - Redo button clicked. + * - :ref:`view/viewModeButton/abstract/clicked ` + - "Abstract view" toggle clicked. + * - :ref:`view/viewModeButton/preview/clicked ` + - "Preview" toggle clicked. + * - :ref:`view/paginationNext/clicked ` + - "Next page" pagination button clicked. + * - :ref:`view/paginationPrevious/clicked ` + - "Previous page" pagination button clicked. + + +.. _apireference-formeditor-jsevents-overview-stage: + +Stage +----- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/stage/abstract/render/template/perform ` + - **Main extension point.** Stage renders a form element that has a + :yaml:`formEditorPartials` entry. + * - :ref:`view/stage/abstract/render/preProcess ` + - Before the abstract stage area is rendered. + * - :ref:`view/stage/abstract/render/postProcess ` + - After the abstract stage area was rendered. + * - :ref:`view/stage/preview/render/postProcess ` + - After the preview stage area was rendered. + * - :ref:`view/stage/element/clicked ` + - A form element in the stage was clicked. + * - :ref:`view/stage/panel/clicked ` + - The stage panel background was clicked. + * - :ref:`view/stage/abstract/button/newElement/clicked ` + - "Add element" button at the bottom of the stage clicked. + * - :ref:`view/stage/abstract/elementToolbar/button/newElement/clicked ` + - Toolbar "add element" / split button on an element clicked. + * - :ref:`view/stage/abstract/dnd/start ` + - Drag started in the stage. + * - :ref:`view/stage/abstract/dnd/change ` + - Drag position changed in the stage. + * - :ref:`view/stage/abstract/dnd/update ` + - Drag ended, model position updated. + * - :ref:`view/stage/abstract/dnd/stop ` + - Drag operation finished. + + +.. _apireference-formeditor-jsevents-overview-inspector: + +Inspector +--------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/inspector/editor/insert/perform ` + - **Extension point for custom inspector editors.** + * - :ref:`view/inspector/collectionElement/new/selected ` + - A new validator/finisher was chosen in the select box. + * - :ref:`view/inspector/collectionElement/existing/selected ` + - An existing validator/finisher section was expanded. + * - :ref:`view/inspector/collectionElements/dnd/update ` + - A validator/finisher was reordered via drag-and-drop. + * - :ref:`view/inspector/removeCollectionElement/perform ` + - Remove a validator/finisher (from RequiredValidatorEditor checkbox). + + +.. _apireference-formeditor-jsevents-overview-structure: + +Structure tree +-------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/structure/root/selected ` + - Root element in the tree was clicked. + * - :ref:`view/structure/button/newPage/clicked ` + - "New page" button in the tree panel clicked. + * - :ref:`view/structure/renew/postProcess ` + - Tree was re-rendered. + * - :ref:`view/tree/node/clicked ` + - A tree node was clicked. + * - :ref:`view/tree/node/changed ` + - A tree node label was edited inline. + * - :ref:`view/tree/render/listItemAdded ` + - Reserved – not yet published by core. (A list item was added to the tree.) + * - :ref:`view/tree/dnd/change ` + - Drag position changed in the tree. + * - :ref:`view/tree/dnd/update ` + - Drag ended, model position updated. + * - :ref:`view/tree/dnd/stop ` + - Drag operation finished. + + +.. _apireference-formeditor-jsevents-overview-modals: + +Dialogs (modals) +---------------- + +.. list-table:: + :header-rows: 1 + :widths: 45 55 + + * - Event + - When it fires + * - :ref:`view/modal/close/perform ` + - User confirmed closing the editor with unsaved changes. + * - :ref:`view/modal/removeFormElement/perform ` + - User confirmed deleting a form element. + * - :ref:`view/modal/removeCollectionElement/perform ` + - User confirmed removing a validator/finisher. + * - :ref:`view/modal/validationErrors/element/clicked ` + - A form element was clicked in the validation-error dialog. + + +.. _apireference-formeditor-jsevents-reference: + +Event reference +=============== + + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-ready: +.. _apireference-formeditor-jsevents-view-ready: + +view/ready +---------- + +Published once all additional view-model modules registered via +:yaml:`dynamicJavaScriptModules.additionalViewModelModules` have +bootstrapped. EXT:form uses this event to remove the loading indicator +and finish editor initialisation. This is the earliest safe point to +interact with the fully wired editor. + +:Arguments: none + +.. literalinclude:: _codesnippets/_view-ready.js + :language: javascript + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-ajax-saveformdefinition-success: +.. _apireference-formeditor-jsevents-core-ajax-savesuccess: + +core/ajax/saveFormDefinition/success +-------------------------------------- + +Published after the form definition was saved successfully. EXT:form +shows a success flash message, updates the in-memory form definition +and re-renders all components. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`{ status: string, formDefinition: object }` + - Response payload; :js:`formDefinition` is the saved definition. + + +.. _apireference-formeditor-jsevents-core-ajax-saveerror: + +core/ajax/saveFormDefinition/error +------------------------------------ + +Published when the save Ajax request returns a server-side error. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`{ status: string, message: string, code: number }` + - Error details from the server. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-ajax-renderformdefinitionpage-success: +.. _apireference-formeditor-jsevents-core-ajax-rendersuccess: + +core/ajax/renderFormDefinitionPage/success +------------------------------------------- + +Published after the preview Ajax request returns successfully. EXT:form +uses this to display the rendered form HTML in the preview stage. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Rendered HTML of the current form page. + * - ``args[1]`` + - :js:`number` + - Zero-based index of the rendered page. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-ajax-error: +.. _apireference-formeditor-jsevents-core-ajax-error: + +core/ajax/error +---------------- + +Published when any Ajax request (save or preview render) fails at the +HTTP level. EXT:form shows an error flash message and displays the raw +error in the preview area. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - HTTP status text (e.g. ``'Internal Server Error'``). + * - ``args[1]`` + - :js:`string` + - Raw response body. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-applicationstate-add: +.. _apireference-formeditor-jsevents-core-applicationstate-add: + +core/applicationState/add +-------------------------- + +Published every time an action (add / remove / move element or +collection element) is pushed onto the undo/redo stack. EXT:form uses +this to enable or disable the undo/redo buttons. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`ApplicationState` + - Snapshot of the application state that was just pushed. + * - ``args[1]`` + - :js:`number` + - Current stack pointer position (0-based). + * - ``args[2]`` + - :js:`number` + - Total number of entries in the undo/redo stack. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-currentlyselectedformelementchanged: +.. _apireference-formeditor-jsevents-core-currentlyselectedformelementchanged: + +core/currentlySelectedFormElementChanged +----------------------------------------- + +Published at the end of :js:`formEditorApp.setCurrentlySelectedFormElement()`. +All components that need to react to a selection change (inspector, stage, +tree highlight) subscribe to this event. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The newly selected FormElement model. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-core-formelement-somepropertychanged: +.. _apireference-formeditor-jsevents-core-formelement-somepropertychanged: + +core/formElement/somePropertyChanged +-------------------------------------- + +Published by the FormElement model whenever a property is written via +:js:`set()`. EXT:form uses this to keep the tree labels, stage and +inspector in sync. It is also the mechanism behind +:ref:`FormElement.on() `. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Dot-separated property path that was written. + * - ``args[1]`` + - :js:`unknown` + - New value. + * - ``args[2]`` + - :js:`unknown` + - Previous value. + * - ``args[3]`` + - :js:`string | undefined` + - :js:`__identifierPath` of the element whose property changed. + +.. literalinclude:: _codesnippets/_some-property-changed.js + :language: javascript + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-formelement-inserted: +.. _apireference-formeditor-jsevents-view-formelement-inserted: + +view/formElement/inserted +-------------------------- + +Published after a new form element has been added to the form definition +tree. EXT:form selects the new element and re-renders tree, stage and +inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The newly inserted FormElement model. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-formelement-moved: +.. _apireference-formeditor-jsevents-view-formelement-moved: + +view/formElement/moved +----------------------- + +Published after a form element has been moved within the tree. EXT:form +does not add additional behaviour here by default. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The moved FormElement model. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-formelement-removed: +.. _apireference-formeditor-jsevents-view-formelement-removed: + +view/formElement/removed +------------------------- + +Published after a form element has been removed. EXT:form selects the +parent element and re-renders tree, stage and inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The parent FormElement model of the deleted element. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-collectionelement-new-added: +.. _apireference-formeditor-jsevents-view-collectionelement-new-added: + +view/collectionElement/new/added +--------------------------------- + +Published after a new validator or finisher has been created and added to +the form definition. EXT:form re-renders the inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the new collection element (e.g. ``'NotEmpty'``). + * - ``args[1]`` + - :js:`string` + - Collection name: ``'validators'`` or ``'finishers'``. + * - ``args[2]`` + - :js:`FormElement` + - The owning form element. + * - ``args[3]`` + - :js:`object` + - Full configuration object of the added collection element. + * - ``args[4]`` + - :js:`string` + - Identifier of the reference element (inserted before/after). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-collectionelement-moved: +.. _apireference-formeditor-jsevents-view-collectionelement-moved: + +view/collectionElement/moved +----------------------------- + +Published after a validator or finisher has been reordered. EXT:form +re-renders the inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the moved element. + * - ``args[1]`` + - :js:`string` + - Relative position: ``'before'`` or ``'after'``. + * - ``args[2]`` + - :js:`string` + - Identifier of the reference element. + * - ``args[3]`` + - :js:`string` + - Collection name. + * - ``args[4]`` + - :js:`FormElement` + - The owning form element. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-collectionelement-removed: +.. _apireference-formeditor-jsevents-view-collectionelement-removed: + +view/collectionElement/removed +-------------------------------- + +Published after a validator or finisher has been removed from the form +definition. EXT:form re-renders the inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the removed element. + * - ``args[1]`` + - :js:`string` + - Collection name. + * - ``args[2]`` + - :js:`FormElement` + - The owning form element. + + +.. _apireference-formeditor-jsevents-view-insertelements-perform-before: + +view/insertElements/perform/before +------------------------------------ + +Published when the user selects an element type in the "New element" +dialog after clicking the "Before" toolbar option. EXT:form creates the +new element and moves it *before* the currently selected element. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Form element type identifier (e.g. ``'Text'``). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-insertelements-perform-after: +.. _apireference-formeditor-jsevents-view-insertelements-perform-after: + +view/insertElements/perform/after +---------------------------------- + +Published when the user selects an element type after clicking the +"After" toolbar option or the standard toolbar button for non-composite +elements. EXT:form creates the element and moves it *after* the selected +element (as a sibling). + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Form element type identifier. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-insertelements-perform-inside: +.. _apireference-formeditor-jsevents-view-insertelements-perform-inside: + +view/insertElements/perform/inside +------------------------------------ + +Published when the user selects an element type after clicking the +"Inside" toolbar option on a composite element (e.g. Fieldset). EXT:form +creates the element as a *child* of the currently selected composite. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Form element type identifier. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-insertelements-perform-bottom: +.. _apireference-formeditor-jsevents-view-insertelements-perform-bottom: + +view/insertElements/perform/bottom +------------------------------------ + +Published when the user selects an element type after clicking the +"Create new element" button at the very bottom of the stage in abstract +view. EXT:form appends the element as the last child of the current page. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Form element type identifier. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-insertpages-perform: +.. _apireference-formeditor-jsevents-view-insertpages-perform: + +view/insertPages/perform +------------------------- + +Published when the user selects a page type in the "New page" dialog. +EXT:form creates the page *after* the currently selected page. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Form element type identifier (typically ``'Page'``). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-header-button-save-clicked: +.. _apireference-formeditor-jsevents-view-header-save: + +view/header/button/save/clicked +--------------------------------- + +Published when the "Save" button is clicked. EXT:form either opens a +validation-error dialog (if there are errors) or saves the form definition. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-header-button-close-clicked: +.. _apireference-formeditor-jsevents-view-header-close: + +view/header/button/close/clicked +---------------------------------- + +Published when the "Close" button is clicked *and* the form has unsaved +changes. EXT:form opens a confirmation dialog. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-header-button-newpage-clicked: +.. _apireference-formeditor-jsevents-view-header-newpage: + +view/header/button/newPage/clicked +------------------------------------ + +Published when the "New page" icon in the header is clicked. EXT:form +opens the "New page" dialog. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`'view/insertPages/perform'` + - The event to publish once the user picks a page type. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-header-formsettings-clicked: +.. _apireference-formeditor-jsevents-view-header-formsettings: + +view/header/formSettings/clicked +---------------------------------- + +Published when the "Form settings" button is clicked. EXT:form selects +the root form element and renders its settings in the inspector. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-undobutton-clicked: +.. _apireference-formeditor-jsevents-view-undobutton: + +view/undoButton/clicked +------------------------ + +Published when the undo button is clicked. EXT:form steps back one state +in the undo/redo stack and re-renders all components. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-redobutton-clicked: +.. _apireference-formeditor-jsevents-view-redobutton: + +view/redoButton/clicked +------------------------ + +Published when the redo button is clicked. EXT:form steps forward one +state in the undo/redo stack and re-renders all components. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-viewmodebutton-abstract-clicked: +.. _apireference-formeditor-jsevents-view-viewmode-abstract: + +view/viewModeButton/abstract/clicked +-------------------------------------- + +Published when the "Abstract view" toggle in the stage header is clicked. +EXT:form switches to abstract view if not already active. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-viewmodebutton-preview-clicked: +.. _apireference-formeditor-jsevents-view-viewmode-preview: + +view/viewModeButton/preview/clicked +------------------------------------- + +Published when the "Preview" toggle in the stage header is clicked. +EXT:form switches to preview view if not already active. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-paginationnext-clicked: +.. _apireference-formeditor-jsevents-view-pagination-next: + +view/paginationNext/clicked +---------------------------- + +Published when the "next page" arrow in the stage header is clicked. +EXT:form advances to the next form page. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-paginationprevious-clicked: +.. _apireference-formeditor-jsevents-view-pagination-previous: + +view/paginationPrevious/clicked +--------------------------------- + +Published when the "previous page" arrow in the stage header is clicked. +EXT:form goes back to the previous form page. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-render-template-perform: +.. _apireference-formeditor-jsevents-view-stage-abstract-render-template-perform: + +view/stage/abstract/render/template/perform +-------------------------------------------- + +**The primary extension point for custom stage rendering.** + +Published by the Stage component for each form element that has a +:yaml:`formEditorPartials` entry in the prototype configuration. Form +elements *without* a :yaml:`formEditorPartials` entry are rendered +automatically by the +:html:`` web component — no +subscriber is needed for those. + +.. note:: + For most custom form elements the web-component approach (no + :yaml:`formEditorPartials`, no subscriber) is sufficient. + Use this event only when you need fully custom DOM inside the stage + that the built-in web component cannot provide. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The FormElement model being rendered. + * - ``args[1]`` + - :js:`HTMLElement` + - Cloned DOM node from the Fluid partial. Populate this via DOM + manipulation. + +**Full example — custom element with a dedicated stage partial:** + +*Fluid partial* (:file:`EXT:my_extension/Resources/Private/Backend/Partials/FormEditor/Stage/MyCustomElement.html`): + +.. literalinclude:: _codesnippets/_stage-template-perform.html + :language: html + +*Prototype YAML configuration:* + +.. literalinclude:: _codesnippets/_stage-template-perform.yaml + :language: yaml + +*JavaScript module:* + +.. literalinclude:: _codesnippets/_stage-template-perform.js + :language: javascript + :caption: EXT:my_extension/Resources/Public/JavaScript/backend/form-editor/view-model.js + + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-render-preprocess: +.. _apireference-formeditor-jsevents-view-stage-abstract-render-preprocess: + +view/stage/abstract/render/preProcess +--------------------------------------- + +Published immediately before the abstract stage area is re-rendered. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-render-postprocess: +.. _apireference-formeditor-jsevents-view-stage-abstract-render-postprocess: + +view/stage/abstract/render/postProcess +---------------------------------------- + +Published immediately after the abstract stage area has been rendered. +EXT:form uses this to re-render the undo/redo buttons and apply validation +error highlights. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-preview-render-postprocess: +.. _apireference-formeditor-jsevents-view-stage-preview-render-postprocess: + +view/stage/preview/render/postProcess +--------------------------------------- + +Published after the preview stage area has been rendered. EXT:form uses +this to re-render the undo/redo buttons. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-element-clicked: +.. _apireference-formeditor-jsevents-view-stage-element-clicked: + +view/stage/element/clicked +--------------------------- + +Published when a form element in the abstract stage is clicked. EXT:form +selects the element, shows its toolbar and re-renders the inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the clicked element. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-panel-clicked: +.. _apireference-formeditor-jsevents-view-stage-panel-clicked: + +view/stage/panel/clicked +------------------------- + +Published when the stage panel header or background area is clicked +(not on a specific form element). + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-button-newelement-clicked: +.. _apireference-formeditor-jsevents-view-stage-abstract-button-newelement: + +view/stage/abstract/button/newElement/clicked +---------------------------------------------- + +Published when the "Create new element" button at the bottom of the +stage (in abstract view) is clicked. EXT:form opens the "New element" +dialog configured to insert at the bottom of the current page. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`'view/insertElements/perform/bottom'` + - Target publish event for the dialog result. + * - ``args[1]`` + - :js:`object | undefined` + - Optional modal configuration. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-elementtoolbar-button-newelement-clicked: +.. _apireference-formeditor-jsevents-view-stage-abstract-toolbar-newelement: + +view/stage/abstract/elementToolbar/button/newElement/clicked +------------------------------------------------------------- + +Published when the "Add element" button or split-button ("Before", +"After", "Inside") in the per-element toolbar is clicked. EXT:form opens +the "New element" dialog with the appropriate target event. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Target event: ``'view/insertElements/perform/before'``, + ``'…/after'`` or ``'…/inside'``. + * - ``args[1]`` + - :js:`object` + - Modal configuration (``disableElementTypes``, + ``onlyEnableElementTypes``). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-dnd-start: +.. _apireference-formeditor-jsevents-view-stage-dnd-start: + +view/stage/abstract/dnd/start +------------------------------- + +Published when a drag operation begins in the abstract stage. EXT:form +adds CSS classes to highlight the dragged element. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement` + - The dragged element's DOM node. + * - ``args[1]`` + - :js:`HTMLElement` + - The drag placeholder DOM node. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-dnd-change: +.. _apireference-formeditor-jsevents-view-stage-dnd-change: + +view/stage/abstract/dnd/change +-------------------------------- + +Published on each positional change during a drag operation in the stage +(SortableJS :js:`onChange`). EXT:form applies hover CSS classes. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement` + - The drag placeholder DOM node. + * - ``args[1]`` + - :js:`string` + - :js:`__identifierPath` of the potential parent element. + * - ``args[2]`` + - :js:`FormElement` + - Innermost enclosing composite element (if any). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-dnd-update: +.. _apireference-formeditor-jsevents-view-stage-dnd-update: + +view/stage/abstract/dnd/update +-------------------------------- + +Published at the end of a drag operation when the element was dropped in a +new position (SortableJS :js:`onEnd`). EXT:form calls +:js:`moveFormElement()` to persist the new order. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement` + - The dropped DOM node. + * - ``args[1]`` + - :js:`string` + - :js:`__identifierPath` of the moved element. + * - ``args[2]`` + - :js:`string` + - :js:`__identifierPath` of the preceding sibling (empty string if first). + * - ``args[3]`` + - :js:`string` + - :js:`__identifierPath` of the following sibling (empty string if last). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-stage-abstract-dnd-stop: +.. _apireference-formeditor-jsevents-view-stage-dnd-stop: + +view/stage/abstract/dnd/stop +------------------------------ + +Published after the drag operation completes and all model updates are +done. EXT:form re-renders tree, stage and inspector and selects the moved +element. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the element that was dragged. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-editor-insert-perform: +.. _apireference-formeditor-jsevents-view-inspector-editor-insert: + +view/inspector/editor/insert/perform +-------------------------------------- + +**Extension point for custom inspector editors.** + +Published after each inspector editor has been rendered (both for form +elements and for collection elements). Use :js:`args[0].templateName` to +identify which editor is being rendered and apply custom logic. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`EditorConfiguration` + - Full YAML configuration of the editor (includes :js:`templateName`). + * - ``args[1]`` + - :js:`HTMLElement` + - The rendered DOM node of the inspector editor. + * - ``args[2]`` + - :js:`string` + - Identifier of the active collection element (validator/finisher), + or empty string when rendering a plain element editor. + * - ``args[3]`` + - :js:`string` + - Collection name (``'validators'`` or ``'finishers'``), or empty. + +**Example — register a custom inspector editor:** + +*Prototype YAML:* + +.. literalinclude:: _codesnippets/_inspector-editor-insert.yaml + :language: yaml + +*JavaScript module:* + +.. literalinclude:: _codesnippets/_inspector-editor-insert.js + :language: javascript + :caption: EXT:my_extension/Resources/Public/JavaScript/backend/form-editor/view-model.js + + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collectionelement-new-selected: +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collection-new-selected: +.. _apireference-formeditor-jsevents-view-inspector-collection-new-selected: + +view/inspector/collectionElement/new/selected +---------------------------------------------- + +Published when the user selects a *new* validator or finisher from the +select box in the inspector. EXT:form adds the collection element to the +form definition and re-renders the inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the selected collection element. + * - ``args[1]`` + - :js:`string` + - Collection name (``'validators'`` or ``'finishers'``). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collectionelement-existing-selected: +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collection-existing-selected: +.. _apireference-formeditor-jsevents-view-inspector-collection-existing-selected: + +view/inspector/collectionElement/existing/selected +---------------------------------------------------- + +Published when the user expands an *existing* validator or finisher row +in the inspector. EXT:form renders that element's sub-editors. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the already-selected collection element. + * - ``args[1]`` + - :js:`string` + - Collection name. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collectionelement-dnd-update: +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-collection-dnd-update: +.. _apireference-formeditor-jsevents-view-inspector-collection-dnd-update: + +view/inspector/collectionElements/dnd/update +--------------------------------------------- + +Published when a validator or finisher is reordered via drag-and-drop +inside the inspector (SortableJS :js:`onEnd`). EXT:form moves the element +in the form definition. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the moved element. + * - ``args[1]`` + - :js:`string` + - Identifier of the preceding element after the move. + * - ``args[2]`` + - :js:`string` + - Identifier of the following element after the move. + * - ``args[3]`` + - :js:`string` + - Collection name. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-inspector-removecollectionelement-perform: +.. _apireference-formeditor-jsevents-view-inspector-removecollectionelement: + +view/inspector/removeCollectionElement/perform +----------------------------------------------- + +Published by the ``RequiredValidatorEditor`` when its checkbox is +unchecked. EXT:form removes the ``NotEmpty`` validator from the form +definition. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Validator identifier (e.g. ``'NotEmpty'``). + * - ``args[1]`` + - :js:`'validators'` + - Collection name (always ``'validators'`` for this event). + * - ``args[2]`` + - :js:`FormElement | undefined` + - The owning form element, or ``undefined`` for the currently + selected one. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-modal-close-perform: +.. _apireference-formeditor-jsevents-view-modal-close: + +view/modal/close/perform +------------------------- + +Published when the user confirms closing the editor in the "unsaved +changes" dialog. EXT:form clears the unsaved-content flag and navigates +back to the form manager. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-modal-removeformelement-perform: +.. _apireference-formeditor-jsevents-view-modal-removeformelement: + +view/modal/removeFormElement/perform +-------------------------------------- + +Published when the user confirms deleting a form element in the +confirmation dialog. EXT:form removes the element from the form +definition. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`FormElement` + - The form element to be deleted. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-modal-removecollectionelement-perform: +.. _apireference-formeditor-jsevents-view-modal-removecollectionelement: + +view/modal/removeCollectionElement/perform +------------------------------------------- + +Published when the user confirms removing a validator or finisher via its +delete icon. EXT:form removes the collection element from the form +definition. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - Identifier of the collection element to remove. + * - ``args[1]`` + - :js:`string` + - Collection name. + * - ``args[2]`` + - :js:`FormElement` + - The owning form element. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-modal-validationerrors-element-clicked: +.. _apireference-formeditor-jsevents-view-modal-validationerrors-clicked: + +view/modal/validationErrors/element/clicked +-------------------------------------------- + +Published when the user clicks a form element link inside the validation +error dialog. EXT:form selects the element and navigates to it. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the element with the validation error. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-structure-root-selected: +.. _apireference-formeditor-jsevents-view-structure-root-selected: + +view/structure/root/selected +------------------------------ + +Published when the root element in the structure tree is clicked. EXT:form +selects the root form element and re-renders stage, tree and inspector. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-structure-button-newpage-clicked: +.. _apireference-formeditor-jsevents-view-structure-button-newpage: + +view/structure/button/newPage/clicked +--------------------------------------- + +Published when the "Create new page" button inside the structure tree panel +is clicked. EXT:form opens the "New page" dialog. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`'view/insertPages/perform'` + - Target publish event for the dialog result. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-structure-renew-postprocess: +.. _apireference-formeditor-jsevents-view-structure-renew-postprocess: + +view/structure/renew/postProcess +---------------------------------- + +Published after the structure tree has been fully re-rendered. EXT:form +uses this to apply validation error markers to tree nodes. + +:Arguments: none + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-node-clicked: +.. _apireference-formeditor-jsevents-view-tree-node-clicked: + +view/tree/node/clicked +----------------------- + +Published when a node in the structure tree is clicked. EXT:form selects +the element and re-renders stage and inspector. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the clicked element. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-node-changed: +.. _apireference-formeditor-jsevents-view-tree-node-changed: + +view/tree/node/changed +----------------------- + +.. versionadded:: 13.4 + This event was previously missing from the documentation. It has been + dispatched since inline label editing in the structure tree was introduced. + +Published when a tree node label is edited inline (inline-rename). EXT:form +writes the new label to the FormElement model and updates the inspector if +the element is currently selected. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the renamed element. + * - ``args[1]`` + - :js:`string` + - The new label string. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-render-listitemadded: +.. _apireference-formeditor-jsevents-view-tree-listitem-added: + +view/tree/render/listItemAdded +-------------------------------- + +.. note:: + This event is defined in the TypeScript event-map interface but is + **not yet published** by the core tree component. It is reserved for + future use. Subscribing to it will currently have no effect. + +Published by the tree component for each form element as it is added to +the rendered tree. Use this to augment individual tree nodes. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement | null` + - The list item DOM node that was added. + * - ``args[1]`` + - :js:`FormElement` + - The FormElement model for this tree node. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-dnd-change: +.. _apireference-formeditor-jsevents-view-tree-dnd-change: + +view/tree/dnd/change +--------------------- + +Published on each positional change during a drag in the structure tree +(SortableJS :js:`onChange`). EXT:form applies hover CSS classes. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement | null` + - The drag placeholder node. + * - ``args[1]`` + - :js:`string` + - :js:`__identifierPath` of the potential parent element. + * - ``args[2]`` + - :js:`FormElement` + - Innermost enclosing composite element (if any). + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-dnd-update: +.. _apireference-formeditor-jsevents-view-tree-dnd-update: + +view/tree/dnd/update +--------------------- + +Published when a drag in the structure tree ends and the element was +dropped in a new position. EXT:form calls :js:`moveFormElement()`. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`HTMLElement | null` + - The dropped DOM node. + * - ``args[1]`` + - :js:`string` + - :js:`__identifierPath` of the moved element. + * - ``args[2]`` + - :js:`string` + - :js:`__identifierPath` of the preceding sibling. + * - ``args[3]`` + - :js:`string` + - :js:`__identifierPath` of the following sibling. + + +.. _apireference-formeditor-basicjavascriptconcepts-events-view-tree-dnd-stop: +.. _apireference-formeditor-jsevents-view-tree-dnd-stop: + +view/tree/dnd/stop +------------------- + +Published after the tree drag operation completes. EXT:form re-renders +tree, stage and inspector and selects the moved element. + +:Arguments: + +.. list-table:: + :widths: 15 25 60 + :header-rows: 1 + + * - Index + - Type + - Description + * - ``args[0]`` + - :js:`string` + - :js:`__identifierPath` of the element that was dragged. + + + diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.js new file mode 100644 index 0000000..0e379ff --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.js @@ -0,0 +1,22 @@ +export function bootstrap(formEditorApp) { + formEditorApp.getPublisherSubscriber().subscribe( + 'view/inspector/editor/insert/perform', + (topic, args) => { + const [editorConfiguration, editorHtml] = args; + + if (editorConfiguration.templateName !== 'Inspector-MyCustomEditor') { + return; + } + + // Wire up your custom editor UI inside editorHtml + const input = editorHtml.querySelector('.my-custom-input'); + if (input) { + input.addEventListener('change', (e) => { + formEditorApp + .getCurrentlySelectedFormElement() + .set(editorConfiguration.propertyPath, e.target.value); + }); + } + }, + ); +} diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.yaml b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.yaml new file mode 100644 index 0000000..accbf3f --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_inspector-editor-insert.yaml @@ -0,0 +1,18 @@ +prototypes: + standard: + formEditor: + dynamicJavaScriptModules: + additionalViewModelModules: + 10: '@vendor/my-extension/backend/form-editor/view-model.js' + formEditorPartials: + Inspector-MyCustomEditor: 'Inspector/MyCustomEditor' + formEditorFluidConfiguration: + partialRootPaths: + 100: 'EXT:my_extension/Resources/Private/Backend/Partials/FormEditor/' + formElementsDefinition: + Text: + formEditor: + editors: + 600: + templateName: 'Inspector-MyCustomEditor' + myOption: 'example' diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_publish.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_publish.js new file mode 100644 index 0000000..016efdd --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_publish.js @@ -0,0 +1,3 @@ +export function bootstrap(formEditorApp) { + formEditorApp.getPublisherSubscriber().publish('my/custom/event', ['arg1', 'arg2']); +} diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_some-property-changed.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_some-property-changed.js new file mode 100644 index 0000000..134dfb7 --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_some-property-changed.js @@ -0,0 +1,11 @@ +export function bootstrap(formEditorApp) { + formEditorApp.getPublisherSubscriber().subscribe( + 'core/formElement/somePropertyChanged', + (topic, args) => { + const [propertyPath, newValue, oldValue, identifierPath] = args; + if (propertyPath === 'label' && identifierPath?.startsWith('my-form/page-1/')) { + console.log('Label changed from', oldValue, 'to', newValue); + } + }, + ); +} diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.html b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.html new file mode 100644 index 0000000..65e815d --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.html @@ -0,0 +1,4 @@ +
+
+
+
diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.js new file mode 100644 index 0000000..88504df --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.js @@ -0,0 +1,24 @@ +export function bootstrap(formEditorApp) { + formEditorApp.getPublisherSubscriber().subscribe( + 'view/stage/abstract/render/template/perform', + (topic, args) => { + const [formElement, template] = args; + + if (formElement.get('type') !== 'MyCustomElement') { + return; + } + + const labelEl = template.querySelector('[data-identifier="elementLabel"]'); + if (labelEl) { + labelEl.textContent = + formElement.get('label') || formElement.get('identifier'); + } + + const summaryEl = template.querySelector('[data-identifier="elementSummary"]'); + if (summaryEl) { + summaryEl.textContent = + formElement.get('properties.myCustomProperty') ?? ''; + } + }, + ); +} diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.yaml b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.yaml new file mode 100644 index 0000000..173ef7d --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_stage-template-perform.yaml @@ -0,0 +1,11 @@ +prototypes: + standard: + formEditor: + dynamicJavaScriptModules: + additionalViewModelModules: + 10: '@vendor/my-extension/backend/form-editor/view-model.js' + formEditorPartials: + FormElement-MyCustomElement: 'Stage/MyCustomElement' + formEditorFluidConfiguration: + partialRootPaths: + 100: 'EXT:my_extension/Resources/Private/Backend/Partials/FormEditor/' diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_subscribe.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_subscribe.js new file mode 100644 index 0000000..a877394 --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_subscribe.js @@ -0,0 +1,11 @@ +export function bootstrap(formEditorApp) { + const ps = formEditorApp.getPublisherSubscriber(); + + // Subscribe – returns a token for later unsubscription + const token = ps.subscribe('view/ready', (topic, args) => { + // args is a typed tuple matching the event signature + }); + + // Unsubscribe + ps.unsubscribe(token); +} diff --git a/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_view-ready.js b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_view-ready.js new file mode 100644 index 0000000..b872891 --- /dev/null +++ b/Documentation/D/FormEditor/JavaScriptEvents/_codesnippets/_view-ready.js @@ -0,0 +1,5 @@ +export function bootstrap(formEditorApp) { + formEditorApp.getPublisherSubscriber().subscribe('view/ready', () => { + // Safe to call any formEditorApp API here. + }); +} diff --git a/Documentation/D/FormEditor/StageTemplates/Index.rst b/Documentation/D/FormEditor/StageTemplates/Index.rst new file mode 100644 index 0000000..3788feb --- /dev/null +++ b/Documentation/D/FormEditor/StageTemplates/Index.rst @@ -0,0 +1,137 @@ +.. include:: /Includes.rst.txt + +.. _apireference-formeditor-stage-commonabstractformelementtemplates: +.. _apireference-formeditor-stagetemplates: + +=============== +Stage templates +=============== + +The **Stage** component renders each form element as an HTML item in the +abstract view. This section explains the two rendering strategies: the +modern web-component approach (recommended) and the legacy Fluid-partial +approach (deprecated). + +.. contents:: + :depth: 1 + :local: + + +.. _apireference-formeditor-stagetemplates-webcomponent: + +Built-in web component (recommended) +===================================== + +When no :yaml:`formEditorPartials` entry exists for a form element type, +the Stage component automatically renders it using the built-in +:html:`` web component. The component +displays the element's label, type icon, validators, select options and +allowed MIME types without requiring any custom JavaScript. + +.. tip:: + For most custom form elements this is the recommended approach. Simply + omit :yaml:`formEditorPartials` from the prototype configuration and the + editor handles the rest. + +Properties set on the web component from the :js:`FormElement` model: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Property + - Source in FormElement model + * - :js:`elementType` + - Form element definition :yaml:`label` + * - :js:`elementLabel` + - :yaml:`label` (falls back to :yaml:`identifier`) + * - :js:`elementIconIdentifier` + - Form element definition :yaml:`iconIdentifier` + * - :js:`validators` + - :yaml:`validators` array (excludes ``NotEmpty``, shown via :js:`isRequired`) + * - :js:`isRequired` + - ``true`` when a ``NotEmpty`` validator is present + * - :js:`options` + - :yaml:`properties.options` (for select-like elements) + * - :js:`allowedMimeTypes` + - :yaml:`properties.allowedMimeTypes` + * - :js:`content` + - :yaml:`properties.text` or :yaml:`properties.contentElementUid` + * - :js:`isHidden` + - ``true`` when :yaml:`renderingOptions.enabled` is ``false`` + + +.. _apireference-formeditor-stagetemplates-fluid: + +Custom Fluid partial (advanced) +================================ + +If you need fully custom stage rendering – for example to display a +proprietary summary of complex properties – you can still provide a Fluid +partial and subscribe to the +:ref:`view/stage/abstract/render/template/perform ` +event to populate it with DOM manipulation. + +The core Fluid partials are located in +:file:`EXT:form/Resources/Private/Backend/Partials/FormEditor/Stage/`. + +.. warning:: + The legacy stage rendering helpers + :js:`renderSimpleTemplateWithValidators()` and + :js:`renderSelectTemplates()` from + :js:`@typo3/form/backend/form-editor/stage-component` are deprecated + since TYPO3 v14.2 and will be removed in TYPO3 v15. Migrate to the + web component approach (omit :yaml:`formEditorPartials`) or implement + custom DOM manipulation in the event subscriber. + +.. _apireference-formeditor-stage-commonabstractformelementtemplates-simpletemplate: +.. _apireference-formeditor-stagetemplates-fluid-simpletemplate: + +Stage/SimpleTemplate (deprecated) +---------------------------------- + +Displays the element :yaml:`label`. When the element has validators, a +validator icon and their labels appear on hover/selection. Rendered via +the deprecated :js:`renderSimpleTemplateWithValidators()`. + +.. deprecated:: 14.2 + Use the :html:`` web component + by omitting :yaml:`formEditorPartials`, or implement custom DOM + manipulation in the + :ref:`view/stage/abstract/render/template/perform ` + subscriber. See Deprecation :issue:`109306`. + +.. _apireference-formeditor-stage-commonabstractformelementtemplates-selecttemplate: +.. _apireference-formeditor-stagetemplates-fluid-selecttemplate: + +Stage/SelectTemplate (deprecated) +---------------------------------- + +Extends ``Stage/SimpleTemplate`` by additionally listing the chosen option +labels from :yaml:`properties.options.*`. Rendered via the deprecated +:js:`renderSelectTemplates()`. + +Example form element using select options: + +.. literalinclude:: _codesnippets/_select-template.yaml + :language: yaml + +The template partial contains a container with the path to read: + +.. literalinclude:: _codesnippets/_select-template-partial.html + :language: html + +For elements using a different array property (e.g. ``FileUpload`` with +:yaml:`properties.allowedMimeTypes`), adjust the :html:`data-template-property` +attribute accordingly: + +.. literalinclude:: _codesnippets/_file-upload-partial.html + :language: html + +The web component handles both cases automatically. + +.. deprecated:: 14.2 + Use the :html:`` web component + by omitting :yaml:`formEditorPartials`. + See `Deprecation: #109306 - Deprecate form editor stage template rendering functions `_. + diff --git a/Documentation/D/FormEditor/StageTemplates/_codesnippets/_file-upload-partial.html b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_file-upload-partial.html new file mode 100644 index 0000000..29b9b3b --- /dev/null +++ b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_file-upload-partial.html @@ -0,0 +1,2 @@ +
diff --git a/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template-partial.html b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template-partial.html new file mode 100644 index 0000000..78c2b8b --- /dev/null +++ b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template-partial.html @@ -0,0 +1,2 @@ +
diff --git a/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template.yaml b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template.yaml new file mode 100644 index 0000000..e2d1e93 --- /dev/null +++ b/Documentation/D/FormEditor/StageTemplates/_codesnippets/_select-template.yaml @@ -0,0 +1,7 @@ +type: MultiCheckbox +identifier: multicheckbox-1 +label: 'Multi checkbox' +properties: + options: + value1: label1 + value2: label2 diff --git a/Documentation/D/FormEditor/_codesnippets/_JavaScriptModules.php b/Documentation/D/FormEditor/_codesnippets/_JavaScriptModules.php new file mode 100644 index 0000000..08f6d15 --- /dev/null +++ b/Documentation/D/FormEditor/_codesnippets/_JavaScriptModules.php @@ -0,0 +1,9 @@ + ['form'], + 'imports' => [ + '@vendor/my-extension/' + => 'EXT:my_extension/Resources/Public/JavaScript/', + ], +]; diff --git a/Documentation/D/FormEditor/_codesnippets/_bootstrap.js b/Documentation/D/FormEditor/_codesnippets/_bootstrap.js new file mode 100644 index 0000000..4f89b1f --- /dev/null +++ b/Documentation/D/FormEditor/_codesnippets/_bootstrap.js @@ -0,0 +1,10 @@ +/** + * Custom form editor module for EXT:my_extension. + */ +export function bootstrap(formEditorApp) { + const ps = formEditorApp.getPublisherSubscriber(); + + ps.subscribe('view/ready', () => { + // Editor is fully initialised – set up your custom logic here. + }); +} diff --git a/Documentation/D/FormEditor/_codesnippets/_prototype-setup.yaml b/Documentation/D/FormEditor/_codesnippets/_prototype-setup.yaml new file mode 100644 index 0000000..08d2aa4 --- /dev/null +++ b/Documentation/D/FormEditor/_codesnippets/_prototype-setup.yaml @@ -0,0 +1,6 @@ +prototypes: + standard: + formEditor: + dynamicJavaScriptModules: + additionalViewModelModules: + 10: '@vendor/my-extension/backend/form-editor/view-model.js' diff --git a/Documentation/D/FrontendRendering/Index.rst b/Documentation/D/FrontendRendering/Index.rst new file mode 100644 index 0000000..b07c0c2 --- /dev/null +++ b/Documentation/D/FrontendRendering/Index.rst @@ -0,0 +1,320 @@ +.. include:: /Includes.rst.txt + + +.. _apireference-frontendrendering: + +============================ +Building and rendering forms +============================ + +This chapter explains how EXT:form renders forms in the frontend and how +developers can build forms programmatically or customize the rendering +pipeline. + +For the complete PHP API of every class mentioned here, see +`EXT:form API on api.typo3.org `__. + +.. contents:: + :local: + :depth: 2 + + +.. _apireference-frontendrendering-fluidformrenderer: + +Template resolution (FluidFormRenderer) +======================================== + +The :php-short:`\TYPO3\CMS\Form\Domain\Renderer\FluidFormRenderer` resolves +Fluid templates, layouts and partials through rendering options defined in the +prototype configuration. All options are read from +:php-short:`\TYPO3\CMS\Form\Domain\Model\FormDefinition::getRenderingOptions()`. + +.. _apireference-frontendrendering-fluidformrenderer-options: + +.. _apireference-frontendrendering-fluidformrenderer-options-templaterootpaths: + +templateRootPaths +----------------- + +Defines one or more paths to Fluid **templates**. +Paths are searched in reverse order (bottom to top); the first match wins. + +Only the root form element (type :yaml:`Form`) must be a **template** file. +All child elements are resolved as **partials**. + +.. literalinclude:: _templateRootPaths.yaml + :caption: EXT:my_sitepackage/Configuration/Form/CustomPrototype.yaml + :language: yaml + +With the default type :yaml:`Form` the renderer expects a file named +:file:`Form.html` inside the first matching path. + + +.. _apireference-frontendrendering-fluidformrenderer-options-layoutrootpaths: + +layoutRootPaths +--------------- + +Defines one or more paths to Fluid **layouts**, searched in reverse order. + +.. literalinclude:: _layoutRootPaths.yaml + :caption: EXT:my_sitepackage/Configuration/Form/CustomPrototype.yaml + :language: yaml + + +.. _apireference-frontendrendering-fluidformrenderer-options-partialrootpaths: + +partialRootPaths +---------------- + +Defines one or more paths to Fluid **partials**, searched in reverse order. + +Within these paths the renderer looks for a file named after the +form element type (e.g. :file:`Text.html` for a :yaml:`Text` element). +Use :ref:`templateName ` +to override this convention. + +.. literalinclude:: _partialRootPaths.yaml + :caption: EXT:my_sitepackage/Configuration/Form/CustomPrototype.yaml + :language: yaml + + +.. _apireference-frontendrendering-fluidformrenderer-options-templatename: + +templateName +------------ + +By default the element type is used as the partial file name +(e.g. type :yaml:`Text` → :file:`Text.html`). +Set :yaml:`templateName` to use a different file instead: + +.. literalinclude:: _templateName.yaml + :caption: EXT:my_sitepackage/Configuration/Form/CustomPrototype.yaml + :language: yaml + +The element of type :yaml:`Foo` now renders using :file:`Text.html`. + + +.. _apireference-frontendrendering-renderviewHelper: + +The render ViewHelper +===================== + +.. _apireference-frontendrendering-renderviewHelper-arguments: + +Use :html:`` in a Fluid template to render a form. +The ViewHelper accepts the following arguments: + + +.. _apireference-frontendrendering-renderviewHelper-persistenceidentifier: + +persistenceIdentifier +--------------------- + +Path to a YAML form definition. This is the most common way to render a +form: + +.. literalinclude:: _renderPersistenceIdentifier.html + :caption: EXT:my_sitepackage/Resources/Private/Templates/ContactPage.html + :language: html + + +.. _apireference-frontendrendering-renderviewHelper-overrideconfiguration: + +overrideConfiguration +--------------------- + +A configuration array that is merged **on top** of the loaded form +definition (or passed directly to the factory when no +:yaml:`persistenceIdentifier` is given). +This allows adjusting a form per usage without duplicating the YAML file. + + +.. _apireference-frontendrendering-renderviewHelper-factoryclass: + +factoryClass +------------ + +A fully qualified class name implementing +:php-short:`\TYPO3\CMS\Form\Domain\Factory\FormFactoryInterface`. +Defaults to :php-short:`\TYPO3\CMS\Form\Domain\Factory\ArrayFormFactory`. +Set a custom factory to :ref:`build forms programmatically `. + +.. literalinclude:: _renderFactoryClass.html + :caption: EXT:my_sitepackage/Resources/Private/Templates/ContactPage.html + :language: html + + +.. _apireference-frontendrendering-renderviewHelper-prototypename: + +prototypeName +------------- + +Name of the prototype the factory should use (e.g. :yaml:`standard`). +If omitted the framework looks for the prototype name inside the form +definition; if none is found, :yaml:`standard` is used. + + +.. _apireference-frontendrendering-programmatically: + +Building forms programmatically +=============================== + +Instead of writing YAML, you can create a form entirely in PHP by +implementing a custom :php:`FormFactory`. + +.. rst-class:: bignums-xxl + +1. Create a FormFactory + + Extend :php:`AbstractFormFactory` and implement :php:`build()`. + Use :php:`FormDefinition::createPage()` to add pages, + :php:`Page::createElement()` to add elements, and + :php:`FormDefinition::createFinisher()` to attach finishers. + + .. literalinclude:: _CustomFormFactory.php + :caption: EXT:my_sitepackage/Classes/Domain/Factory/CustomFormFactory.php + :language: php + +2. Render the form + + Reference your factory in a Fluid template: + + .. literalinclude:: _renderFactoryClass.html + :caption: EXT:my_sitepackage/Resources/Private/Templates/ContactPage.html + :language: html + + +.. _apireference-frontendrendering-programmatically-key-concepts: + +Key classes and their responsibilities +-------------------------------------- + +.. _apireference-frontendrendering-programmatically-apimethods-formruntime: + +The following table lists the most important classes you work with when +building or manipulating forms programmatically. Use your IDE's +autocompletion or the +`API documentation `__ +for the full method reference. + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Class + - Purpose + + * - :php-short:`\TYPO3\CMS\Form\Domain\Model\FormDefinition` + - The complete form model. Create pages (:php:`createPage()`), + attach finishers (:php:`createFinisher()`), look up elements + (:php:`getElementByIdentifier()`), and bind to a request + (:php:`bind()`). + + * - :php-short:`\TYPO3\CMS\Form\Domain\Runtime\FormRuntime` + - A *bound* form instance (created by :php:`FormDefinition::bind()`). + Provides access to the current page, submitted values + (:php:`getElementValue()`), and the request/response objects. + This is the object available inside finishers and event listeners. + + * - :php-short:`\TYPO3\CMS\Form\Domain\Model\FormElements\Page` + - One page of a multi-step form. Add elements with + :php:`createElement()`, reorder them with :php:`moveElementBefore()` + / :php:`moveElementAfter()`. + + * - :php-short:`\TYPO3\CMS\Form\Domain\Model\FormElements\Section` + - A grouping element inside a page. Same API as :php:`Page` for + managing child elements. + + * - :php-short:`\TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement` + - Base class of all concrete elements. Most element types use + :php-short:`\TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement`; + specialized subclasses include, e.g. + :php-short:`\TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload`. + Set properties (:php:`setProperty()`), add validators + (:php:`createValidator()`), define default values + (:php:`setDefaultValue()`). + + * - :php-short:`\TYPO3\CMS\Form\Domain\Configuration\ConfigurationService` + - Reads the merged prototype configuration. + Call :php:`getPrototypeConfiguration('standard')` to obtain the + full array for a prototype. + + +.. _apireference-frontendrendering-programmatically-initializeformelement: + +Initializing elements at runtime +--------------------------------- + +Override :php:`initializeFormElement()` in a custom form element class to +populate data (e.g. from a database) when the element is added to the form. +At that point the prototype defaults have already been applied; properties +from the YAML definition are applied **afterwards**. + +.. tip:: + If you only need to initialize an element without writing a full custom + class, listen to the :php:`BeforeRenderableIsAddedToFormEvent` PSR-14 + event instead. See :ref:`apireference-events`. + + +.. _apireference-frontendrendering-finishers: + +Working with finishers +====================== + +Custom finishers extend :php-short:`\TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher` +and place their logic in :php:`executeInternal()`. The base class provides: + +:php:`parseOption(string $optionName)` + Resolves a finisher option, applying form-element variable replacements + and TypoScript-style option overrides. Always prefer this over direct + array access. + +The :php-short:`\TYPO3\CMS\Form\Domain\Finishers\FinisherContext` passed to +:php:`execute()` gives access to: + +:php:`getFormRuntime()` + The :php-short:`\TYPO3\CMS\Form\Domain\Runtime\FormRuntime` for the current + submission. + +:php:`getFormValues()` + All submitted values (after validation and property mapping). + +:php:`getFinisherVariableProvider()` + A key/value store to **share data between finishers** within the same + request. The returned + :php-short:`\TYPO3\CMS\Form\Domain\Finishers\FinisherVariableProvider` offers: + + :php:`add(string $finisherIdentifier, string $key, mixed $value)` + Store a value under a finisher-specific namespace. + + :php:`get(string $finisherIdentifier, string $key, mixed $default = null)` + Retrieve a previously stored value (returns :php:`$default` if not set). + + :php:`exists(string $finisherIdentifier, string $key)` + Check whether a value has been stored. + + :php:`remove(string $finisherIdentifier, string $key)` + Remove a stored value. + +:php:`cancel()` + Stops execution of any remaining finishers. + +.. seealso:: + :ref:`Accessing finisher options ` | + :ref:`Sharing data between finishers ` + + +.. _apireference-frontendrendering-runtimemanipulation: + +Runtime manipulation +==================== + +.. _apireference-frontendrendering-runtimemanipulation-events: + +EXT:form dispatches PSR-14 events at every important step of the rendering +lifecycle. Use them to modify the form, redirect page flow, or adjust +submitted values – without subclassing framework internals. + +.. seealso:: + :ref:`PSR-14 events overview for EXT:form ` diff --git a/Documentation/D/FrontendRendering/_CustomFormFactory.php b/Documentation/D/FrontendRendering/_CustomFormFactory.php new file mode 100644 index 0000000..ba74c2a --- /dev/null +++ b/Documentation/D/FrontendRendering/_CustomFormFactory.php @@ -0,0 +1,78 @@ +getPrototypeConfiguration( + $prototypeName, + ); + + $form = GeneralUtility::makeInstance( + FormDefinition::class, + 'ContactForm', + $prototypeConfiguration, + ); + $form->setRenderingOption('controllerAction', 'index'); + + // Page 1 – personal data + $page1 = $form->createPage('page1'); + + /** @var AbstractFormElement $name */ + $name = $page1->createElement('name', 'Text'); + $name->setLabel('Name'); + $name->createValidator('NotEmpty'); + + /** @var AbstractFormElement $email */ + $email = $page1->createElement('email', 'Text'); + $email->setLabel('Email'); + + // Page 2 – message + $page2 = $form->createPage('page2'); + + /** @var AbstractFormElement $message */ + $message = $page2->createElement('message', 'Textarea'); + $message->setLabel('Message'); + $message->createValidator('StringLength', ['minimum' => 5, 'maximum' => 500]); + + // Radio buttons + /** @var AbstractFormElement $subject */ + $subject = $page2->createElement('subject', 'RadioButton'); + $subject->setProperty('options', [ + 'general' => 'General inquiry', + 'support' => 'Support request', + ]); + $subject->setLabel('Subject'); + + // Finisher – send email + $form->createFinisher('EmailToSender', [ + 'subject' => 'Contact form submission', + 'recipients' => [ + 'info@example.com' => 'My Company', + ], + 'senderAddress' => 'noreply@example.com', + ]); + + $this->triggerFormBuildingFinished($form); + + return $form; + } +} diff --git a/Documentation/D/FrontendRendering/_layoutRootPaths.yaml b/Documentation/D/FrontendRendering/_layoutRootPaths.yaml new file mode 100644 index 0000000..1449870 --- /dev/null +++ b/Documentation/D/FrontendRendering/_layoutRootPaths.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + 20: 'EXT:my_sitepackage/Resources/Private/Forms/Frontend/Layouts/' diff --git a/Documentation/D/FrontendRendering/_partialRootPaths.yaml b/Documentation/D/FrontendRendering/_partialRootPaths.yaml new file mode 100644 index 0000000..9c74eb1 --- /dev/null +++ b/Documentation/D/FrontendRendering/_partialRootPaths.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + 20: 'EXT:my_sitepackage/Resources/Private/Forms/Frontend/Partials/' diff --git a/Documentation/D/FrontendRendering/_renderFactoryClass.html b/Documentation/D/FrontendRendering/_renderFactoryClass.html new file mode 100644 index 0000000..c6114a8 --- /dev/null +++ b/Documentation/D/FrontendRendering/_renderFactoryClass.html @@ -0,0 +1,3 @@ + diff --git a/Documentation/D/FrontendRendering/_renderPersistenceIdentifier.html b/Documentation/D/FrontendRendering/_renderPersistenceIdentifier.html new file mode 100644 index 0000000..00a1359 --- /dev/null +++ b/Documentation/D/FrontendRendering/_renderPersistenceIdentifier.html @@ -0,0 +1,3 @@ + diff --git a/Documentation/D/FrontendRendering/_templateName.yaml b/Documentation/D/FrontendRendering/_templateName.yaml new file mode 100644 index 0000000..c68d5a2 --- /dev/null +++ b/Documentation/D/FrontendRendering/_templateName.yaml @@ -0,0 +1,6 @@ +prototypes: + standard: + formElementsDefinition: + Foo: + renderingOptions: + templateName: 'Text' diff --git a/Documentation/D/FrontendRendering/_templateRootPaths.yaml b/Documentation/D/FrontendRendering/_templateRootPaths.yaml new file mode 100644 index 0000000..6330c25 --- /dev/null +++ b/Documentation/D/FrontendRendering/_templateRootPaths.yaml @@ -0,0 +1,8 @@ +prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + 20: 'EXT:my_sitepackage/Resources/Private/Forms/Frontend/Templates/' diff --git a/Documentation/D/Index.rst b/Documentation/D/Index.rst new file mode 100644 index 0000000..2265530 --- /dev/null +++ b/Documentation/D/Index.rst @@ -0,0 +1,20 @@ +.. include:: /Includes.rst.txt +.. _apireference: + +============================== +For Developers / API Reference +============================== + +This chapter is a complete reference of the API of the form framework. It +mainly addresses your concerns as a developer. + +.. toctree:: + :maxdepth: 1 + + Events/Index + FormEditor/Index + FrontendRendering/Index + +.. seealso:: + All built-in finishers including their options and programmatic usage + is now described in: `Ready-to-use finishers `_. diff --git a/Documentation/E/Accessibility/Index.rst b/Documentation/E/Accessibility/Index.rst new file mode 100644 index 0000000..a2e4c1f --- /dev/null +++ b/Documentation/E/Accessibility/Index.rst @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt + +.. _accessibility: + +============= +Accessibility +============= + +There are numerous accessibility rules when it comes to making a form accessible +to a large number of users. This includes accessibility to groups such as people +with a disability, the elderly, non-native speakers, etc. + +The following should be kept in mind by editors creating forms +in the backend form editor: + +Labels +====== + +Always use clear, descriptive labels in the :guilabel:`Label` field. Simply +putting the label in field :guilabel:`Placeholder` is not +considered accessible. + +Descriptions +============ + +Add an extended description in the field :guilabel:`Description`. + +Placeholder +=========== + +The :guilabel:`Placeholder` field should not contain the label. +It should contain example content to make filling out the field easier for +users. + +Autocomplete +============ + +The autocomplete property should be used whenever a field contains personal +information. This property can then be used by assistive +technology to aid users to fill out forms. Select the desired purpose from the +select :guilabel:`Autocomplete`. See `Input Purposes for User Interface +Components at w3.org `__ for +an explanation of which purposes to use. + +If additional input purposes are needed, your integrator or developer can +:ref:`add additional input purpose options `. diff --git a/Documentation/E/Finishers/Images/form_finishers_overview.png b/Documentation/E/Finishers/Images/form_finishers_overview.png new file mode 100644 index 0000000..661d5a4 Binary files /dev/null and b/Documentation/E/Finishers/Images/form_finishers_overview.png differ diff --git a/Documentation/E/Finishers/Index.rst b/Documentation/E/Finishers/Index.rst new file mode 100644 index 0000000..9e76138 --- /dev/null +++ b/Documentation/E/Finishers/Index.rst @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +.. _finishers: +.. _finishers-introduction: +.. _finishers-overview-of-finishers: + +========= +Finishers +========= + +Any number of "finishers" can be added to a form. Finishers are actions that will +be executed once the form has been submitted by a user. + +In the following chapter, each finisher and its function will be explained. Not all +finishers can be added via the form editor. There are some +finishers that can only be added by integrators/ administrators. The following +finishers are available by default: + +* :ref:`Email to sender (form submitter) ` +* :ref:`Email to receiver (you) ` +* :ref:`Redirect to a page ` +* :ref:`Delete uploads ` +* :ref:`Confirmation message ` + +.. figure:: Images/form_finishers_overview.png + :alt: Form editor - add new finishers. + + Form editor - add new finishers + +.. important:: + + Finishers are executed in the order that they appear in your form definition. + This is particularly important for the ``Redirect finisher``. Make sure + this finisher is the very last one to be executed. The ``Redirect finisher`` + stops the execution of all subsequent finishers in order to perform the redirect. + Finishers defined after the ``Redirect finisher`` will be ignored. diff --git a/Documentation/E/FormElements/Images/form_elements_advancedPassword_1.png b/Documentation/E/FormElements/Images/form_elements_advancedPassword_1.png new file mode 100644 index 0000000..0c651ae Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_advancedPassword_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_advancedPassword_2.png b/Documentation/E/FormElements/Images/form_elements_advancedPassword_2.png new file mode 100644 index 0000000..3300850 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_advancedPassword_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_all.png b/Documentation/E/FormElements/Images/form_elements_all.png new file mode 100644 index 0000000..aa1731b Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_all.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_checkbox_1.png b/Documentation/E/FormElements/Images/form_elements_checkbox_1.png new file mode 100644 index 0000000..5e1b5ec Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_checkbox_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_checkbox_2.png b/Documentation/E/FormElements/Images/form_elements_checkbox_2.png new file mode 100644 index 0000000..2cc7a81 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_checkbox_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_contentElement_1.png b/Documentation/E/FormElements/Images/form_elements_contentElement_1.png new file mode 100644 index 0000000..70c3f4f Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_contentElement_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_contentElement_2.png b/Documentation/E/FormElements/Images/form_elements_contentElement_2.png new file mode 100644 index 0000000..6dcd6e6 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_contentElement_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_datePicker_1.png b/Documentation/E/FormElements/Images/form_elements_datePicker_1.png new file mode 100644 index 0000000..e8825e3 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_datePicker_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_datePicker_2.png b/Documentation/E/FormElements/Images/form_elements_datePicker_2.png new file mode 100644 index 0000000..aff3f00 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_datePicker_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_date_1.png b/Documentation/E/FormElements/Images/form_elements_date_1.png new file mode 100644 index 0000000..004c541 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_date_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_date_2.png b/Documentation/E/FormElements/Images/form_elements_date_2.png new file mode 100644 index 0000000..57d032f Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_date_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_email_1.png b/Documentation/E/FormElements/Images/form_elements_email_1.png new file mode 100644 index 0000000..5451db0 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_email_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_email_2.png b/Documentation/E/FormElements/Images/form_elements_email_2.png new file mode 100644 index 0000000..fe3d0dc Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_email_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_fieldset_1.png b/Documentation/E/FormElements/Images/form_elements_fieldset_1.png new file mode 100644 index 0000000..862a74e Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_fieldset_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_fieldset_2.png b/Documentation/E/FormElements/Images/form_elements_fieldset_2.png new file mode 100644 index 0000000..1daa01c Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_fieldset_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_fieldset_3.png b/Documentation/E/FormElements/Images/form_elements_fieldset_3.png new file mode 100644 index 0000000..eddcde9 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_fieldset_3.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_fileUpload_1.png b/Documentation/E/FormElements/Images/form_elements_fileUpload_1.png new file mode 100644 index 0000000..a8bce1c Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_fileUpload_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_fileUpload_2.png b/Documentation/E/FormElements/Images/form_elements_fileUpload_2.png new file mode 100644 index 0000000..a8f73eb Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_fileUpload_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_grid_1.png b/Documentation/E/FormElements/Images/form_elements_grid_1.png new file mode 100644 index 0000000..0a8408b Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_grid_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_grid_2.png b/Documentation/E/FormElements/Images/form_elements_grid_2.png new file mode 100644 index 0000000..0a4b20d Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_grid_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_grid_3.png b/Documentation/E/FormElements/Images/form_elements_grid_3.png new file mode 100644 index 0000000..be5f74d Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_grid_3.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_grid_4.png b/Documentation/E/FormElements/Images/form_elements_grid_4.png new file mode 100644 index 0000000..d9d2f8a Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_grid_4.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_hidden_1.png b/Documentation/E/FormElements/Images/form_elements_hidden_1.png new file mode 100644 index 0000000..c54a62b Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_hidden_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_hidden_2.png b/Documentation/E/FormElements/Images/form_elements_hidden_2.png new file mode 100644 index 0000000..d0b7140 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_hidden_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_imageUpload_1.png b/Documentation/E/FormElements/Images/form_elements_imageUpload_1.png new file mode 100644 index 0000000..88bf6e2 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_imageUpload_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_imageUpload_2.png b/Documentation/E/FormElements/Images/form_elements_imageUpload_2.png new file mode 100644 index 0000000..11f29f5 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_imageUpload_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_multiCheckbox_1.png b/Documentation/E/FormElements/Images/form_elements_multiCheckbox_1.png new file mode 100644 index 0000000..d54ce73 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_multiCheckbox_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_multiCheckbox_2.png b/Documentation/E/FormElements/Images/form_elements_multiCheckbox_2.png new file mode 100644 index 0000000..9a49f9a Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_multiCheckbox_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_multiSelect_1.png b/Documentation/E/FormElements/Images/form_elements_multiSelect_1.png new file mode 100644 index 0000000..d321a85 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_multiSelect_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_multiSelect_2.png b/Documentation/E/FormElements/Images/form_elements_multiSelect_2.png new file mode 100644 index 0000000..03e94c1 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_multiSelect_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_number_1.png b/Documentation/E/FormElements/Images/form_elements_number_1.png new file mode 100644 index 0000000..5e89a25 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_number_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_number_2.png b/Documentation/E/FormElements/Images/form_elements_number_2.png new file mode 100644 index 0000000..dbb47fe Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_number_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_password_1.png b/Documentation/E/FormElements/Images/form_elements_password_1.png new file mode 100644 index 0000000..9c388ad Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_password_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_password_2.png b/Documentation/E/FormElements/Images/form_elements_password_2.png new file mode 100644 index 0000000..b5b1792 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_password_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_radioBtn_1.png b/Documentation/E/FormElements/Images/form_elements_radioBtn_1.png new file mode 100644 index 0000000..73eec51 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_radioBtn_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_radioBtn_2.png b/Documentation/E/FormElements/Images/form_elements_radioBtn_2.png new file mode 100644 index 0000000..9b204ea Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_radioBtn_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_singleSelect_1.png b/Documentation/E/FormElements/Images/form_elements_singleSelect_1.png new file mode 100644 index 0000000..ab8ff5e Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_singleSelect_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_singleSelect_2.png b/Documentation/E/FormElements/Images/form_elements_singleSelect_2.png new file mode 100644 index 0000000..3d2771f Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_singleSelect_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_staticText_1.png b/Documentation/E/FormElements/Images/form_elements_staticText_1.png new file mode 100644 index 0000000..43a0ec0 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_staticText_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_staticText_2.png b/Documentation/E/FormElements/Images/form_elements_staticText_2.png new file mode 100644 index 0000000..4a7dc1b Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_staticText_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_telephone_1.png b/Documentation/E/FormElements/Images/form_elements_telephone_1.png new file mode 100644 index 0000000..c02fbe2 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_telephone_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_telephone_2.png b/Documentation/E/FormElements/Images/form_elements_telephone_2.png new file mode 100644 index 0000000..7273145 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_telephone_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_text_1.png b/Documentation/E/FormElements/Images/form_elements_text_1.png new file mode 100644 index 0000000..4a22349 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_text_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_text_2.png b/Documentation/E/FormElements/Images/form_elements_text_2.png new file mode 100644 index 0000000..ec90057 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_text_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_textarea_1.png b/Documentation/E/FormElements/Images/form_elements_textarea_1.png new file mode 100644 index 0000000..c831b8e Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_textarea_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_textarea_2.png b/Documentation/E/FormElements/Images/form_elements_textarea_2.png new file mode 100644 index 0000000..2ccbee0 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_textarea_2.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_url_1.png b/Documentation/E/FormElements/Images/form_elements_url_1.png new file mode 100644 index 0000000..1dc21fe Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_url_1.png differ diff --git a/Documentation/E/FormElements/Images/form_elements_url_2.png b/Documentation/E/FormElements/Images/form_elements_url_2.png new file mode 100644 index 0000000..247d3a9 Binary files /dev/null and b/Documentation/E/FormElements/Images/form_elements_url_2.png differ diff --git a/Documentation/E/FormElements/Index.rst b/Documentation/E/FormElements/Index.rst new file mode 100644 index 0000000..c1041d4 --- /dev/null +++ b/Documentation/E/FormElements/Index.rst @@ -0,0 +1,651 @@ +.. include:: /Includes.rst.txt + + +.. _form-elements: + +================================== +Form elements and their properties +================================== + + +.. _form-elements-overview-of-form-elements: + +Overview of form elements +------------------------- + +.. figure:: Images/form_elements_all.png + :alt: Overview of all form elements included in the TYPO3 core. There may + be fewer or different elements in your installation. + + Overview of all form elements included in TYPO3. There may be + fewer or different elements in your installation. + + +.. _form-elements-settings: + +Form element settings +--------------------- + +Most form elements have these 7 basic settings: + +- **Label**: Label of the element. +- **Description**: Description of the element. Can be used to + provide the user with more information about the expected input. +- **Placeholder**: Example of the expected content. Disappears with the user's + input. +- **Default value**: Preset value. Pre-entered by the system and does not + disappear with the user's input. +- **Mandatory field**: Specify whether the field is a mandatory field and thus + must be filled in by the user. +- **Custom error message**: Custom message that will be displayed to the user + if the field is not filled in. If you don't provide a message, a default + message is shown. +- **Validators**: Validators are used to check the data entered in the + field. The system displays error messages if there are errors. + +.. warning:: + + If a form element is a required field or validators fail, error + messages are displayed by the browser. These error texts and formatting cannot be + changed by editors or integrators as they are controlled + by the browser/operating system. + + +.. _form-elements-basic-elements: + +Basic form elements +------------------- + + +.. _form-elements-basic-elements-text: + +Text +==== + +A single-line text field, e.g. for entering short information such as name, +address, location. This element has the +:ref:`basic settings `. + +.. figure:: Images/form_elements_text_1.png + :alt: Element 'Text' - preview in the frontend. + + Element 'Text' - preview in the frontend. + +.. figure:: Images/form_elements_text_2.png + :alt: Settings for the 'Text' element. + + Settings for the 'Text' element. + + +.. _form-elements-basic-elements-textarea: + +Textarea +======== + +A multi-line text field, e.g. for the free input of continuous text. This allows +the user to provide a short text such as a message. This element has the +:ref:`basic settings `. + +.. figure:: Images/form_elements_textarea_1.png + :alt: Element 'Textarea' - preview in the frontend. + + Element 'Textarea' - preview in the frontend. + +.. figure:: Images/form_elements_textarea_2.png + :alt: Settings for the 'Textarea' element. + + Settings for the 'Textarea' element. + + +.. _form-elements-basic-elements-password: + +Password +======== + +A single-line text field for entering a password. The browser "hides" the text +input, i.e. the entered characters are not visible. This element has the +:ref:`basic settings `. + +.. figure:: Images/form_elements_password_1.png + :alt: Element 'Password' - preview in the frontend. + + Element 'Password' - preview in the frontend. + +.. figure:: Images/form_elements_password_2.png + :alt: Settings for the 'Password' element. + + Settings for the 'Password' element. + + +.. _form-elements-special-elements: + +Special elements +================ + +Sometimes it is better to use special elements instead of simple text +elements. Mobile devices such as smartphones display on-screen keyboards. If you +use the "Email address" element the form field on the device will contain a +"@" character in a central position and a validator will be triggered +that checks for the input format "firstname.lastname@example.org". + + +.. _form-elements-special-elements-email: + +Email address +============== + +A single-line field for entering an email address. This element has the +:ref:`basic settings `. In addition, the field has an +`Email` validator (this is the only validator available for this form element). + +.. figure:: Images/form_elements_email_1.png + :alt: Element 'E-mail' - preview in the frontend. + + Element 'E-mail' - preview in the frontend. + +.. figure:: Images/form_elements_email_2.png + :alt: Settings for the 'E-mail' element. + + Settings for the 'E-mail' element. + + +.. _form-elements-special-elements-telephone-number: + +Telephone number +================ + +A single-line text field for entering a phone number. This element has the +:ref:`basic settings `. + +.. figure:: Images/form_elements_telephone_1.png + :alt: Element 'Telephone' - preview in the frontend. + + Element 'Telephone' - preview in the frontend. + +.. figure:: Images/form_elements_telephone_2.png + :alt: Settings for the 'Telephone' element. + + Settings for the 'Telephone' element. + + +.. _form-elements-special-elements-url: + +URL +=== + +A single-line text field for entering a URL. A URL is typically an internet +address, such as that of your website. This element has the +:ref:`basic settings ` + +.. figure:: Images/form_elements_url_1.png + :alt: Element 'URL' - preview in the frontend. + + Element 'URL' - preview in the frontend. + +.. figure:: Images/form_elements_url_2.png + :alt: Settings for the 'URL' element. + + Settings for the 'URL' element. + + +.. _form-elements-special-elements-number: + +Number +====== + +A single-line text field for entering a number. A user can increase and decrease +the number in preconfigured steps using visual controls in the browser. +This element has the :ref:`basic settings `. +By default, the field has a `Number` validator. Additional settings: + +- **Step**: Here you can enter a number that defines the step size. The step size + is the amount by which a number is increased or decreased in the frontend. + +.. figure:: Images/form_elements_number_1.png + :alt: Element 'Number' - preview in the frontend. + + Element 'Number' - preview in the frontend. + +.. figure:: Images/form_elements_number_2.png + :alt: Settings for the 'Number' element. + + Settings for the 'Number' element. + + +.. _form-elements-special-elements-date: + +Date +==== + +A single-line text field for entering a date. +`Most modern browsers `_ will also display a calendar from +which the user can select the date. This element has the +:ref:`basic settings `. Additional settings: + +- **Frequency**: default value "1" means that the user can select every day. + +.. figure:: Images/form_elements_date_1.png + :alt: Element 'Date' - preview in the frontend. + + Element 'Date' - preview in the frontend. + +.. figure:: Images/form_elements_date_2.png + :alt: Settings for the 'Date' element. + + Settings for the 'Date' element. + + +.. _form-elements-select-elements: + +Select elements +--------------- + +Select elements (including checkboxes, radio buttons and selectboxes) do not +allow a user to enter text. Instead, they offer a predefined +number of choices, for example, salutation options. + +.. note:: + + Select elements behave differently to text fields if they are marked as + "required".Checkboxes with multiple choices, for example, cannot be + be required fields. This is not supported by the HTML standard. + + +.. _form-elements-select-elements-checkbox: + +Checkbox +======== + +A simple checkbox. This element has the :ref:`basic settings `. + +.. figure:: Images/form_elements_checkbox_1.png + :alt: Element 'Checkbox' - preview in the frontend. + + Element 'Checkbox' - preview in the frontend. + +.. figure:: Images/form_elements_checkbox_2.png + :alt: Settings for the 'Checkbox' element. + + Settings for the 'Checkbox' element. + + +.. _form-elements-select-elements-single-select: + +Single selectbox +================ + +An element to create a drop-down list. This element has the +:ref:`basic settings `. Additional settings: + +- **First option**: Define the "empty option", i.e. the first element of the + selectbox. You can use this to provide additional guidance for the user. +- **Choices**: A tool to insert and manage options. + - **Label**: Name of the option. + - **Value**: Value of the option. The system automatically sets the + "Value" to the "Label". You can leave it like this if you are + unsure of what you are doing. + - **Selected**: Check this to pre-select an option in the frontend. + - **[ + ]**: Adds a new line for a new option. + +.. figure:: Images/form_elements_singleSelect_1.png + :alt: Element 'Single select' - preview in the frontend. + + Element 'Single select' - preview in the frontend. + +.. figure:: Images/form_elements_singleSelect_2.png + :alt: Settings for the 'Single select' element. + + Settings for the 'Single select' element. + + +.. _form-elements-select-elements-radiobutton: + +Radio buttons +============= + +An element to display one or more radio buttons. This element has the +:ref:`basic settings `. Additional settings: + +- **Choices**: A tool to insert and manage the options. + - **Label**: Name of the option. + - **Value**: Value of the option. The system automatically sets the + "Value" to the "Label". You can leave it like this if you are + unsure of what you are doing. + - **Selected**: Check this to pre-select an option in the frontend. + - **[ + ]**: Adds a new line for a new option. + +.. figure:: Images/form_elements_radioBtn_1.png + :alt: Element 'Radio button' - preview in the frontend. + + Element 'Radio button' - preview in the frontend. + +.. figure:: Images/form_elements_radioBtn_2.png + :alt: Settings for the 'Radio button' element. + + Settings for the 'Radio button' element. + + +.. _form-elements-select-elements-multi-checkbox: + +Multi checkbox +============== + +An element to create one or more checkboxes. This element has the +:ref:`basic settings `. Additional settings: + +- **Choices**: A tool to insert and manage the options. + - **Label**: Name of the option. + - **Value**: Value of the option. The system automatically sets the + "Value" to the "Label". You can leave it like this if you are + unsure of what you are doing. + - **Selected**: Check this to pre-select an option in the frontend. + - **[ + ]**: Adds a new line for a new option. + +.. figure:: Images/form_elements_multiCheckbox_1.png + :alt: Element 'Multi checkbox' - preview in the frontend. + + Element 'Multi checkbox' - preview in the frontend. + +.. figure:: Images/form_elements_multiCheckbox_2.png + :alt: Settings for the 'Multi checkbox' element. + + Settings for the 'Multi checkbox' element. + +.. warning:: + + **HTML** does not check that "required" fields are filled out. They + are only checked after a form has been submitted. + + +.. _form-elements-select-elements-multi-select: + +Multi select +============ + +An element to create a multiple selection. This element has the +:ref:`basic settings `. Additional settings: + +- **First option**: Define the "empty option", i.e. the first element of the + select. You can use this to provide additional guidance for the user. +- **Choices**: A tool to insert and manage the options. + - **Label**: Name of the option. + - **Value**: Value of the option. The system automatically sets the + "Value" to the "Label". You can leave it like this if you are + unsure of what you are doing. + - **Selected**: Check this to pre-select an option in the frontend. + - **[ + ]**: Adds a new line for a new option. + +.. figure:: Images/form_elements_multiSelect_1.png + :alt: Element 'Multi select' - preview in the frontend. + + Element 'Multi select' - preview in the frontend. + +.. figure:: Images/form_elements_multiSelect_2.png + :alt: Settings for the 'Multi select' element. + + Settings for the 'Multi select' element. + + +.. _form-elements-select-elements-country-select: + +Country select +============== + +An element to create a country selectbox. This element has the +:ref:`basic settings ` Additional settings: + +- **First option**: Define the "empty option", i.e. the first element of the + select. You can use this to provide additional guidance for the user. +- **Prioritized countries**: A multi-selection of country names, which should + be listed as the top options in the form element. +- **Only countries**: Restrict the countries to be rendered in the selection. +- **Exclude countries**: Define which countries should not appear in the + selection. + + +.. _form-elements-advanced-elements: + +Advanced elements +----------------- + + +.. _form-elements-advanced-elements-file-upload: + +File upload +=========== + +An element to upload a file to the :guilabel:`File > Filelist` module. This element has the +:ref:`basic settings `. Additional settings: + +- **Allowed Mime Types**: Select the allowed file extensions a user is able to + upload. +- **Storage path for uploads**: Select the storage path in your TYPO3 installation. + This is where the uploaded file will be saved. + +.. figure:: Images/form_elements_fileUpload_1.png + :alt: Element 'File upload' - preview in the frontend. + + Element 'File upload' - preview in the frontend. + +.. figure:: Images/form_elements_fileUpload_2.png + :alt: Settings for the 'File upload' element. + + Settings for the 'File upload' element. + +.. error:: + + **Privacy issues**: + Keep in mind that the storage path you choose may not be protected. The path may + be indexed by your search and search engines. If you need to protect sensitive + documents, contact your administrator to create a secure storage path. + + +.. _form-elements-advanced-elements-hidden: + +Hidden +====== + +A field that is not visible in the frontend. The form element is inside the red +rectangle in the image. Such a field might be needed for technical functionality, +e.g. to add hidden values to a form. This element has the +:ref:`basic settings `. Additional settings: + +- **Value**: Here you can set a value for the element. + +.. figure:: Images/form_elements_hidden_1.png + :alt: Element 'Hidden' - preview in the frontend. + + Element 'Hidden' - preview in the frontend. + +.. figure:: Images/form_elements_hidden_2.png + :alt: Settings for the 'Hidden' element. + + Settings for the 'Hidden' element. + + +.. _form-elements-advanced-elements-image-upload: + +Image upload +============ + +An element to upload an image to :guilabel:`File > Filelist`. This element has the +:ref:`basic settings `. Other settings: + +- **Allowed Mime Types**: Select the file extensions a user is allowed to + upload. +- **Storage path for uploads**: Select the storage path in your TYPO3 installation. + This is where the uploaded file will be saved. + +.. figure:: Images/form_elements_imageUpload_1.png + :alt: Element 'Image upload' - preview in the frontend. + + Element 'Image upload' - preview in the frontend. + +.. figure:: Images/form_elements_imageUpload_2.png + :alt: Settings for the 'Image upload' element. + + Settings for the 'Image upload' element. + +.. error:: + + **Privacy issues**: + Keep in mind that the storage path you choose may not be protected. The path may + be indexed by your search and search engines. If you need to protect sensitive + documents, contact your administrator to create a secure storage path. + + +.. _form-elements-advanced-elements-advanced-password: + +Advanced password +================= + +The element is analogous to the `Password` form element. A single-line text +field is displayed for entering a password. The browser "hides" the text input, +i.e. the entered characters are not visible. Another field is displayed below it +so that the user has to repeat the password to prevent typing errors. This field +is useful for registration forms. This element has the +:ref:`basic settings `. Additional settings: + +- **Confirmation label**: Label for the confirmation field. + +.. figure:: Images/form_elements_advancedPassword_1.png + :alt: Element 'Advanced password' - preview in the frontend. + + Element 'Advanced password' - preview in the frontend. + +.. figure:: Images/form_elements_advancedPassword_2.png + :alt: Settings for the 'Advanced password' element. + + Settings for the 'Advanced password' element. + + +.. _form-elements-advanced-elements-static-text: + +Static text +=========== + +A field for static text. This text cannot be formatted, which means you can't +insert links or highlight text. Instead, the text is output in the style of +your website. The settings for this element are: + +- **Heading**: Heading for the element. +- **Text**: Content for the element. + +.. figure:: Images/form_elements_staticText_1.png + :alt: Element 'Static text' - preview in the frontend. + + Element 'Static text' - preview in the frontend. + +.. figure:: Images/form_elements_staticText_2.png + :alt: Settings for the 'Static text' element. + + Settings for the 'Static text' element. + + +.. _form-elements-advanced-elements-content-element: + +Content element +================ + +You can display any content elements that are on your website. The settings for +this element are: + +- **Content element uid**: ID of the content element you want to display. You can + either enter the ID manually or select it via the page tree. + To do this, click on the "Page content" button. +- **[ Page content ]**: Modal which displays the page tree. You can select + a page and the content element. + +.. figure:: Images/form_elements_contentElement_1.png + :alt: Element 'Content element' - preview in the frontend. + + Element 'Content element' - preview in the frontend. + +.. figure:: Images/form_elements_contentElement_2.png + :alt: Settings for the 'Content element' element. + + Settings for the 'Content element' element. + + +.. _form-elements-container-elements: + +Container elements +------------------ + +Fieldset and grid elements are container elements that structure +your form in terms of content or visual appearance. Container elements can +be combined. For example, a fieldset can contain several grids. + + +.. _form-elements-container-elements-fieldset: + +Fieldset +======== + +This container groups form elements based on content. This is +important for screen readers and helps you to improve the accessibility of your form. +For example, in an "Address" fieldset you could have +street, house number, postal code and city form elements. The settings for +this element are: + +- **Field group name**: Heading for the field group, e.g. "Address". + +.. figure:: Images/form_elements_fieldset_1.png + :alt: Element 'Fieldset' - preview in the frontend. + + Element 'Fieldset' - preview in the frontend. + +.. figure:: Images/form_elements_fieldset_2.png + :alt: Element 'Fieldset' - preview in the backend. + + Element 'Fieldset' - preview in the backend. + +.. figure:: Images/form_elements_fieldset_3.png + :alt: Settings for the 'Fieldset' element. + + Settings for the 'Fieldset' element. + + +.. _form-elements-container-elements-grid: + +Grid +==== + +Use this container element to place fields next to each other (create a visual structure). + +**The additional settings apply to the content elements inside the grid**: + +- **Configuration Grid Area**: + - Areas: **xs** (Very small), **sm** (Small), **md** (Medium), **lg** (Large), + **xl** (Extra large), **xxl** (Extra extra large). + - These are the "breakpoints". These are ranges of + resolutions or adaptations to different screen sizes. Smartphones, + for example, have a low resolution range (xs or sm) and desktop monitors + have a high resolution range (lg, xl or xxl). Use this to + abstractly control how many elements are displayed next to each other in + which resolution. +- **Number of columns for grid area "xx"**: + - Enter a number for the selected area. + - The number determines how much space the field takes up on the different + screen sizes and therefore how many elements are displayed next to + each other. + +.. figure:: Images/form_elements_grid_1.png + :alt: Element 'Grid' - preview in the frontend. + + Element 'Grid' - preview in the frontend. + +.. figure:: Images/form_elements_grid_2.png + :alt: Element 'Grid' - preview in the backend. + + Element 'Grid' - preview in the backend. + +.. figure:: Images/form_elements_grid_3.png + :alt: Settings for the 'Grid' element - Part 1. + + Settings for the 'Grid' element - Part 1. + +.. figure:: Images/form_elements_grid_4.png + :alt: Settings for the 'Grid' element - Part 2. + + Settings for the 'Grid' element - Part 2. diff --git a/Documentation/E/Index.rst b/Documentation/E/Index.rst new file mode 100644 index 0000000..f5aa537 --- /dev/null +++ b/Documentation/E/Index.rst @@ -0,0 +1,61 @@ +.. include:: /Includes.rst.txt + +.. _forEditors: + +=========== +For Editors +=========== + +Introduction to forms +--------------------- + +Forms are provided by the **Form TYPO3 extension**. Form is a TYPO3 core +extension which has been available by default since TYPO3 version 8. + +What can Form do? +----------------- + +- TYPO3 core extension +- flexible, extensible and easy to use +- easy to use via drag-and-drop +- live preview +- form reuse +- create templates for new forms +- set mandatory fields +- set finishers (downstream processing) +- automatic spam protection +- multi-step forms + +What can't Form do? +------------------- + +Form has limited: + +- formatting of form labels +- multilingual support +- possibilities for textual design of emails + +When can I use Form? +-------------------- + +- for contact forms +- for application forms +- for simple or complex forms +- for different forms on my pages + +Notes on data protection +------------------------ + +Data submitted in forms is not stored in the TYPO3 backend due to privacy reasons. +There are TYPO3 extensions that retrofit this behavior but we do not recommend using these +extensions. Instead, check if the form data can be transferred directly to your +CRM or similar tools. + +.. toctree:: + :maxdepth: 1 + + FormElements/Index + Validators/Index + Finishers/Index + Accessibility/Index + Tutorials/Index diff --git a/Documentation/E/Tutorials/BasicForm/Images/10_chosenFormInCE.png b/Documentation/E/Tutorials/BasicForm/Images/10_chosenFormInCE.png new file mode 100644 index 0000000..7f3b8cb Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/10_chosenFormInCE.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/10_elementWizard.png b/Documentation/E/Tutorials/BasicForm/Images/10_elementWizard.png new file mode 100644 index 0000000..1c86470 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/10_elementWizard.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/11_finishedForm.png b/Documentation/E/Tutorials/BasicForm/Images/11_finishedForm.png new file mode 100644 index 0000000..67825e0 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/11_finishedForm.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/1_newForm.png b/Documentation/E/Tutorials/BasicForm/Images/1_newForm.png new file mode 100644 index 0000000..72bc790 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/1_newForm.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard1.png b/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard1.png new file mode 100644 index 0000000..5a2fd45 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard1.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard2.png b/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard2.png new file mode 100644 index 0000000..ec67765 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/2_newForm_wizard2.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/3_createElement_1.png b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_1.png new file mode 100644 index 0000000..d718850 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_1.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/3_createElement_2.png b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_2.png new file mode 100644 index 0000000..962c228 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_2.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/3_createElement_3.png b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_3.png new file mode 100644 index 0000000..f96b738 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/3_createElement_3.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/3_newForm_wizard3.png b/Documentation/E/Tutorials/BasicForm/Images/3_newForm_wizard3.png new file mode 100644 index 0000000..5adbca7 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/3_newForm_wizard3.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/4_lastName.png b/Documentation/E/Tutorials/BasicForm/Images/4_lastName.png new file mode 100644 index 0000000..38933b0 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/4_lastName.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/5_email.png b/Documentation/E/Tutorials/BasicForm/Images/5_email.png new file mode 100644 index 0000000..c3fc649 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/5_email.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/6_textarea_1.png b/Documentation/E/Tutorials/BasicForm/Images/6_textarea_1.png new file mode 100644 index 0000000..5375a5d Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/6_textarea_1.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/6_textarea_2.png b/Documentation/E/Tutorials/BasicForm/Images/6_textarea_2.png new file mode 100644 index 0000000..9b52821 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/6_textarea_2.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_1.png b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_1.png new file mode 100644 index 0000000..7a45b47 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_1.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_2.png b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_2.png new file mode 100644 index 0000000..f8b513c Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_2.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_3.png b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_3.png new file mode 100644 index 0000000..2b505e5 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_3.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_4.png b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_4.png new file mode 100644 index 0000000..0eca21d Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/7_addFinisherEmail_4.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/85_preview.png b/Documentation/E/Tutorials/BasicForm/Images/85_preview.png new file mode 100644 index 0000000..6e7cc02 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/85_preview.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_1.png b/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_1.png new file mode 100644 index 0000000..b145d75 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_1.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_2.png b/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_2.png new file mode 100644 index 0000000..cd10d63 Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/8_addFinisherConfirmation_2.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Images/9_selectPageForForm.png b/Documentation/E/Tutorials/BasicForm/Images/9_selectPageForForm.png new file mode 100644 index 0000000..286d1eb Binary files /dev/null and b/Documentation/E/Tutorials/BasicForm/Images/9_selectPageForForm.png differ diff --git a/Documentation/E/Tutorials/BasicForm/Index.rst b/Documentation/E/Tutorials/BasicForm/Index.rst new file mode 100644 index 0000000..b9887e3 --- /dev/null +++ b/Documentation/E/Tutorials/BasicForm/Index.rst @@ -0,0 +1,219 @@ +.. include:: /Includes.rst.txt + + +.. _editors-basicForm: + +=========================== +Create a basic contact form +=========================== + +In this tutorial, you will learn how to create a basic contact form. + +Let's define what we need: + +- contact information from our visitors: first name, last name, email address +- the message from our visitor: a text area where they can enter their message +- an email to us with their message +- a confirmation message to the visitor after the form has been submitted + +All fields will be required fields. + +Let's get started: + +.. rst-class:: bignums-xxl + +#. Create a new form + + Go to the :guilabel:`Web > Forms` module and create a new form by clicking on "Create new form". + + .. figure:: Images/1_newForm.png + :alt: The form module - click the button + + The form module without any forms - click the button to create one. + +#. Choose a name + + Choose a name for your form - something you will recognize later on - and click "Next" + + .. figure:: Images/2_newForm_wizard1.png + :alt: The form creation wizard - step 1 + +#. Click "Next" + + As we are creating a basic form, step 2 is done automatically and we go to step 3. Click "Next" again. + + .. figure:: Images/2_newForm_wizard2.png + :alt: The form creation wizard - step 3 + +#. Create new element + + The form editor view will now display your new form as below. Click on "Create new element" to add a field to your form. + + .. figure:: Images/3_createElement_1.png + :alt: Create New Element Button + +#. Add "First Name" + + Create a simple text field for the first name by clicking on "Text" in "Basic Elements". + + .. figure:: Images/3_createElement_2.png + :alt: Create New Text Element + +#. Set options for "First Name" + + Options for your new text field will be displayed in the inspector panel on the right: + + .. figure:: Images/3_createElement_3.png + :alt: Fields for a simple text field + + Fields for a simple text field. + + 1. Label: Enter a label for your field - in this case "First Name". + 2. Description: Enter a description - something that helps your users to know what they should enter. + 3. Placeholder: Enter an example value for the field - this will be used as placeholder in the frontend. + 4. Required Field: Click the checkbox to make your field required. + 5. Enter an error message for users who forget to fill out the field. + 6. Add a "Non-XML text" validator to only allow simple text input. + +#. Repeat + + Repeat the steps in 6 for the "Last Name" field. + + .. figure:: Images/4_lastName.png + :alt: Fields for the "Last Name" text field. + +#. Add Email address + + Now add an email field. Choose type `email`. Set an error message for if the validation fails. + + .. figure:: Images/5_email.png + :alt: Fields for the email field. + +#. Add textarea for message + + Add a `Textarea` field where the user can enter a message. + + .. figure:: Images/6_textarea_1.png + :alt: Choose textarea field. + + The "Textarea" type in the overview. + +#. Add options for the message field + + Set label, description and error messages. + + .. figure:: Images/6_textarea_2.png + :alt: Configure textarea field. + + Configure the message field. + +#. Send an email on form submit + + When a user submits a form, we want to be sent an email by TYPO3. In a form, + this is what is called "a finisher" as it happens when the form is "finished". + + .. figure:: Images/7_addFinisherEmail_1.png + :alt: Adding a finisher + + Adding a finisher + + 1. Click on the form name on the top left - here you can edit general form settings. + 2. Choose a finisher on the right. To send an email to yourself, choose "Email to receiver (you)". + +#. Configure the email finisher + + Choose a subject, the recipient, name and CC. + + .. figure:: Images/7_addFinisherEmail_2.png + :alt: Configuring the finisher + + .. figure:: Images/7_addFinisherEmail_3.png + :alt: Configuring the finisher - part two + + You can use fields from the form to pre-fill values using the `{+}` button. + Here we configure the sender's name from the first and last names in the form. + +#. Save the form + + Click on "Save" to save the current state of the form. Even if your form + isn't complete, it's a good idea to save your state frequently to minimize + the risk of losing data. + + .. figure:: Images/7_addFinisherEmail_4.png + :alt: Saving the form + +#. Add confirmation finisher + + Add a "Confirmation message" finisher to display a confirmation/ thank you + message to the user after they have submitted the form. + + .. figure:: Images/8_addFinisherConfirmation_1.png + :alt: Choose confirmation finisher + +#. Add confirmation message + + Set a "Thank You" message in the "Confirmation Finisher" options. + + .. figure:: Images/8_addFinisherConfirmation_2.png + :alt: Set a confirmation message + +#. Preview the form + + Your form is now fully configured and ready to be added to website pages. Save it again and let's preview it. + + .. figure:: Images/85_preview.png + :alt: Preview the form + + 1. Click on the preview icon and see a rudimentary preview of your form. Notice the "Step" headline. + +#. Remove the "Step" headline + + The "Step" headline above does not make much sense, as there is only a single + step in our form before a user submits it and the headline should be taken + from the page where we will insert the form. To remove it, leave the preview + and click on "Step" in the tree view on the left side. Delete the word "Step". + +#. Save the form + + Save the form and check everything is ok - now it looks fine. Let's go and insert it on a page. + +#. Choose a page for your form + + Your form can now be added to a web page. Go to the page module and choose a web page. + + .. figure:: Images/9_selectPageForForm.png + :alt: Select a page for your form + + 1. Go to the page module. + 2. Choose a page in the page tree (for example: "Contact" for the Contact form :)). + 3. Click on `+ Content` to create a new content element for your form. + +#. Insert Plugin + + In the content element wizard, choose "Form" (in "Form elements" tab). + + .. figure:: Images/10_elementWizard.png + :alt: Select a page for your form + +#. Choose your form definition + + In the plugin tab, choose the form definition you just created. + + .. figure:: Images/10_chosenFormInCE.png + :alt: Choose the form definition + + Having a separate form definition allows you to insert the form on many web pages. + You can then customize fields, for example, the headline, by using the "normal" TYPO3 + header field to render a headline for your form. + +#. Save the content element and enjoy! + + Save the content element and view your web page. You can now see your completed form. + + .. figure:: Images/11_finishedForm.png + :alt: The finished form + + Depending on your frontend, your form might look different. + + Congratulations! You have created a fully functional contact form. + diff --git a/Documentation/E/Tutorials/Index.rst b/Documentation/E/Tutorials/Index.rst new file mode 100644 index 0000000..f708067 --- /dev/null +++ b/Documentation/E/Tutorials/Index.rst @@ -0,0 +1,13 @@ +.. include:: /Includes.rst.txt + + +.. _editorTutorials: + +========= +Tutorials +========= + +.. toctree:: + + BasicForm/Index + PhotoContest/Index diff --git a/Documentation/E/Tutorials/PhotoContest/Images/10_saveTheForm.png b/Documentation/E/Tutorials/PhotoContest/Images/10_saveTheForm.png new file mode 100644 index 0000000..177fb43 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/10_saveTheForm.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/11_selectPage.png b/Documentation/E/Tutorials/PhotoContest/Images/11_selectPage.png new file mode 100644 index 0000000..f55022c Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/11_selectPage.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/12_chooseForm.png b/Documentation/E/Tutorials/PhotoContest/Images/12_chooseForm.png new file mode 100644 index 0000000..3f52e40 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/12_chooseForm.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/13_chooseFormDefinition.png b/Documentation/E/Tutorials/PhotoContest/Images/13_chooseFormDefinition.png new file mode 100644 index 0000000..eaa445e Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/13_chooseFormDefinition.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_1.png b/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_1.png new file mode 100644 index 0000000..3009d0b Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_2.png b/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_2.png new file mode 100644 index 0000000..9626df1 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/14_frontend_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/15_addEmail.png b/Documentation/E/Tutorials/PhotoContest/Images/15_addEmail.png new file mode 100644 index 0000000..4915439 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/15_addEmail.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_1.png b/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_1.png new file mode 100644 index 0000000..2427d41 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_2.png b/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_2.png new file mode 100644 index 0000000..afcd706 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/16_addRedirect_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/17_thankYouPage.png b/Documentation/E/Tutorials/PhotoContest/Images/17_thankYouPage.png new file mode 100644 index 0000000..e716d5d Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/17_thankYouPage.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/1_createForm.png b/Documentation/E/Tutorials/PhotoContest/Images/1_createForm.png new file mode 100644 index 0000000..51c3b4d Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/1_createForm.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_1.png b/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_1.png new file mode 100644 index 0000000..7f53345 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_2.png b/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_2.png new file mode 100644 index 0000000..3388775 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/2_wizard_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_1.png b/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_1.png new file mode 100644 index 0000000..091d591 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_2.png b/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_2.png new file mode 100644 index 0000000..319f3bc Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/3_createElement_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_1.png b/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_1.png new file mode 100644 index 0000000..4895567 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_2.png b/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_2.png new file mode 100644 index 0000000..05688ee Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/4_createImageUpload_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_1.png b/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_1.png new file mode 100644 index 0000000..28218e2 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_2.png b/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_2.png new file mode 100644 index 0000000..9d5aa82 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/5_createStaticText_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/6_setOptionsForStep.png b/Documentation/E/Tutorials/PhotoContest/Images/6_setOptionsForStep.png new file mode 100644 index 0000000..a98cb4b Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/6_setOptionsForStep.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_1.png b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_1.png new file mode 100644 index 0000000..faface8 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_2.png b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_2.png new file mode 100644 index 0000000..1a95a51 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_3.png b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_3.png new file mode 100644 index 0000000..70b0d4d Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/7_createSummary_3.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/8_preview.png b/Documentation/E/Tutorials/PhotoContest/Images/8_preview.png new file mode 100644 index 0000000..23c71fc Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/8_preview.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_1.png b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_1.png new file mode 100644 index 0000000..544a560 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_1.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_2.png b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_2.png new file mode 100644 index 0000000..a60ea10 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_2.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_3.png b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_3.png new file mode 100644 index 0000000..e8bc19e Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_3.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_4.png b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_4.png new file mode 100644 index 0000000..147a3c9 Binary files /dev/null and b/Documentation/E/Tutorials/PhotoContest/Images/9_missingEmail_4.png differ diff --git a/Documentation/E/Tutorials/PhotoContest/Index.rst b/Documentation/E/Tutorials/PhotoContest/Index.rst new file mode 100644 index 0000000..2872d88 --- /dev/null +++ b/Documentation/E/Tutorials/PhotoContest/Index.rst @@ -0,0 +1,255 @@ + +.. include:: /Includes.rst.txt + + +.. _editors-photoContest: + +=========================== +Create a photo contest form +=========================== + +In this tutorial, you will learn how to create a photo contest with the form framework. + +Let's define what we need: + +- contact information from our visitors: name and email address +- a photo upload for our visitors +- an email to us with the participation +- terms and conditions for our contest +- a thank you page after submitting the form + +Let's get started: + +.. rst-class:: bignums-xxl + +#. Create a new form + + Go to the ``Forms`` module and create a new form by clicking on "Create new form". + + .. figure:: Images/1_createForm.png + :alt: The form module - click the button + + The form module with one form - click the button to create a new one. + +#. Choose a name + + Choose a name for your form - something you will recognize later on - and click "Next" + + .. figure:: Images/2_wizard_1.png + :alt: The form creation wizard - step 1 + +#. Click "Next" + + As we are creating a basic form, step 2 will be automatically done and we directly see step 3. Click "Next" again. + + .. figure:: Images/2_wizard_2.png + :alt: The form creation wizard - step 3 + +#. Create new element + + You will now see the form editor view for your new form. Click on "Create new element" to add a field to your form. The first field we want to create is the "Name". Choose "Text" from "Basic Elements" to create a simple text field for the first name. + + .. figure:: Images/3_createElement_1.png + :alt: Create New Element Button + +#. Set options for "Name" + + After selecting the "Text" type, we get new options in the inspector panel: + + .. figure:: Images/3_createElement_2.png + :alt: Fields for a simple text field + + Fields for a simple text field. + + 1. Label: Enter a label for your field - in this case "Name". + 2. Placeholder: Enter an example value for the field - this will be used as placeholder in the frontend. + 3. Add a validator "Non-XML text" to only allow simple text input. + +#. Create image upload field + + Similar to the previous field, add an image upload field. Choose type `Image Upload`. + + .. figure:: Images/4_createImageUpload_1.png + :alt: Create Image Upload + +#. Configure image upload field + + Set options for the image upload - for example choose specific image formats or enter a max file size. + + .. figure:: Images/4_createImageUpload_2.png + :alt: Configure Image Upload + + The options of the image upload. + +#. Create "Terms and Conditions" + + To display terms and conditions for our contest, we want to add a simple static text to the form. Choose "Static Text" from the available element types. + + .. figure:: Images/5_createStaticText_1.png + :alt: The static text type + + Choose "Static Text". + +#. Enter "Terms and Conditions" + + Fill the text box with the terms and conditions for your contest. + + .. figure:: Images/5_createStaticText_2.png + :alt: Set options for Static Text + + Set options for static text. + +#. Change the headline and buttons + + We want to have a nice headline for the form and the next button should read "Summary". To do that, click on "Step" (1) in the form tree and set the fields (2,3) on the right. You don't need to change the previous label, as we are on the first page and there is no previous in this case. + + .. figure:: Images/6_setOptionsForStep.png + :alt: Set options for step + +#. Create a summary page + + We want to create a summary page where the user can confirm his or her data again. Click on "Create new step" on the left to create a new page/step in the form. + + .. figure:: Images/7_createSummary_1.png + :alt: Create new step + + Create a new step in a form. + + .. figure:: Images/7_createSummary_2.png + :alt: Create new step - choose summary + + Choose summary as type for your new step + + .. figure:: Images/7_createSummary_3.png + :alt: Create new step - configure summary + + Configure the summary headline and button labels. + +#. Preview the form + + Click on the preview button to preview the form. + + .. figure:: Images/8_preview.png + :alt: Preview the form + + Preview the form. + + Oh no! We forgot to create the email field. Let's do that next. + +#. Add an email field + + Go back to editing the form (1) and click on "Create new element" (2). + + .. figure:: Images/9_missingEmail_1.png + :alt: Switch to editing and Create new element + + Switch to editing and create new element + + .. figure:: Images/9_missingEmail_2.png + :alt: Choose "email address" + + The "email address" type + + .. figure:: Images/9_missingEmail_3.png + :alt: Configure the email address field + + Configure the email address field. + + .. figure:: Images/9_missingEmail_4.png + :alt: Move the email address field + + Move the email address field to a better position via drag and drop. + +#. Save the form + + Your form is now fully configured and ready to be inserted on pages. + + .. figure:: Images/10_saveTheForm.png + :alt: Save the form + + Save the form. + + You can save the form and do another review - now it looks fine. Let's go and insert it on a page. + +#. Choose a page for your form + + The form you configured can now be inserted on any page you want. Go to the page module and choose one. + + .. figure:: Images/11_selectPage.png + :alt: Select a page for your form + + 1. Go to the page module. + 2. Choose a page in the page tree (for example: "Contest"). + 3. Click on `+ Content` to create a new content element. + +#. Insert Plugin + + From the content element wizard, choose "Form" (in "Form elements" tab). + + .. figure:: Images/12_chooseForm.png + :alt: Choose form as type + +#. Choose your form definition + + In the plugin tab, choose the form definition you just created. You can also use the "normal" TYPO3 fields like header to render a headline for your form. + + .. figure:: Images/13_chooseFormDefinition.png + :alt: Choose the form definition + + Having a separate form definition allows you to insert the form on many pages, customizing for example the headline in each case. + +#. Save the content element + + Save the content element and go and view your web page. You can now see your finished form. + + .. figure:: Images/14_frontend_1.png + :alt: The finished form - Step 1 + + Depending on your frontend, your form might look different. + + .. figure:: Images/14_frontend_2.png + :alt: The finished form - Step 2 + + Depending on your frontend, your summary page might look different. + + When testing your form, you might notice that it doesn't do anything yet when we fill it. That's bad. Let's change that. + +#. Add email finisher + + Everytime someone fills the form we want to receive an email with the contest picture. Let's add an email finisher for that: + + .. figure:: Images/15_addEmail.png + :alt: Add email finisher + + Configure the email finisher + +#. Add redirect to "Thank You" page + + After submitting the form we want to redirect the user to a thank you page. There's a ready-made finisher for that, too - the "Redirect to a page" finisher: + + .. figure:: Images/16_addRedirect_1.png + :alt: Redirect Finisher Options + + Redirect finisher with options. + + Choose "Redirect to a page" from the finisher menu. Click on the "Page" button to open the page browser. + + .. figure:: Images/16_addRedirect_2.png + :alt: Page browser of redirect finisher. + + Page browser. + + Choose your thank you page. + + .. attention:: + + Make sure that the redirect finisher is the last finisher - after the redirect no other finishers will be executed. + +#. Test again - Enjoy! + + Save the form and reload the frontend. Now you can test the form again. After submitting you will now be redirected to the thank you page. + + .. figure:: Images/17_thankYouPage.png + :alt: Thank you page. + + Depending on your frontend, your page might look different. diff --git a/Documentation/E/Validators/Images/form_validators.png b/Documentation/E/Validators/Images/form_validators.png new file mode 100644 index 0000000..25da0c1 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators.png differ diff --git a/Documentation/E/Validators/Images/form_validators_alphanumeric.png b/Documentation/E/Validators/Images/form_validators_alphanumeric.png new file mode 100644 index 0000000..141d16b Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_alphanumeric.png differ diff --git a/Documentation/E/Validators/Images/form_validators_dateRange.png b/Documentation/E/Validators/Images/form_validators_dateRange.png new file mode 100644 index 0000000..0ca114b Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_dateRange.png differ diff --git a/Documentation/E/Validators/Images/form_validators_dateTime.png b/Documentation/E/Validators/Images/form_validators_dateTime.png new file mode 100644 index 0000000..de89a25 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_dateTime.png differ diff --git a/Documentation/E/Validators/Images/form_validators_email.png b/Documentation/E/Validators/Images/form_validators_email.png new file mode 100644 index 0000000..6f14769 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_email.png differ diff --git a/Documentation/E/Validators/Images/form_validators_fileSize.png b/Documentation/E/Validators/Images/form_validators_fileSize.png new file mode 100644 index 0000000..169b681 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_fileSize.png differ diff --git a/Documentation/E/Validators/Images/form_validators_floatingPointNumber.png b/Documentation/E/Validators/Images/form_validators_floatingPointNumber.png new file mode 100644 index 0000000..3d3fd74 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_floatingPointNumber.png differ diff --git a/Documentation/E/Validators/Images/form_validators_integerNumber.png b/Documentation/E/Validators/Images/form_validators_integerNumber.png new file mode 100644 index 0000000..d9b7b72 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_integerNumber.png differ diff --git a/Documentation/E/Validators/Images/form_validators_number.png b/Documentation/E/Validators/Images/form_validators_number.png new file mode 100644 index 0000000..027c85e Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_number.png differ diff --git a/Documentation/E/Validators/Images/form_validators_numberOfSubmittedValues.png b/Documentation/E/Validators/Images/form_validators_numberOfSubmittedValues.png new file mode 100644 index 0000000..41c323b Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_numberOfSubmittedValues.png differ diff --git a/Documentation/E/Validators/Images/form_validators_numberRange.png b/Documentation/E/Validators/Images/form_validators_numberRange.png new file mode 100644 index 0000000..1a58081 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_numberRange.png differ diff --git a/Documentation/E/Validators/Images/form_validators_regularExpression.png b/Documentation/E/Validators/Images/form_validators_regularExpression.png new file mode 100644 index 0000000..46e099d Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_regularExpression.png differ diff --git a/Documentation/E/Validators/Images/form_validators_stringLength.png b/Documentation/E/Validators/Images/form_validators_stringLength.png new file mode 100644 index 0000000..3643316 Binary files /dev/null and b/Documentation/E/Validators/Images/form_validators_stringLength.png differ diff --git a/Documentation/E/Validators/Index.rst b/Documentation/E/Validators/Index.rst new file mode 100644 index 0000000..e1b4062 --- /dev/null +++ b/Documentation/E/Validators/Index.rst @@ -0,0 +1,333 @@ +.. include:: /Includes.rst.txt + + +.. _validators: + +========== +Validators +========== + + +.. _validators-introduction: + +Introduction +------------ + +Validators can be added to all form elements to check user input for "validity" - +i.e. existence, meaningfulness and correctness. For example, you can +determine whether a field has been filled out or if the user has entered a +valid email address. You can also **define** your own **error messages**. +These messages can be edited in the **form editor**. + +This chapter **describes** the individual validators and their +**function**. + +.. figure:: Images/form_validators.png + :alt: In the Inspector - adding validators. + + In the Inspector - adding validators. + + +.. _validators-overview-of-validators: + +Overview of validators +---------------------- + + +.. _validators-alphanumeric: + +Alphanumeric +============ + +This validator checks whether the field contains an alphanumeric string. +"Alphanumeric" means a combination of alphabetic and numeric characters. No +special characters can be entered, only characters from **[A-Z] and [0-9]**. +The settings of the validator are as follows: + +- **Custom error message**: Custom error message that will be shown if the + validator fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` + +.. figure:: Images/form_validators_alphanumeric.png + :alt: In the Inspector - Settings of the "Alphanumeric" validator. + + In the Inspector - Settings of the "Alphanumeric" validator. + + +.. _validators-string-length: + +String length +============= + +This validator uses *minimum* and *maximum* values to check how many +characters can be **entered**. The settings of the validator are as follows: + +- **Minimum**: Minimum amount of characters the field can contain. +- **Maximum**: Maximum amount of characters the field can contain. +- **Custom error message**: Custom error message that will be shown if the + validator fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` + +.. figure:: Images/form_validators_stringLength.png + :alt: In the Inspector - settings of the validator "String length". + + In the Inspector - settings of the validator "String length". + + +.. _validators-email: + +Email +===== + +This validator checks whether an entered value is a **valid email address**. +International characters and multiple occurrences of the **@ sign** +are allowed by default. The settings of the validator are as follows: + +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Email address"` (validator is + automatically active) +- :ref:`"Password"` +- :ref:`"Advanced password"` + +.. figure:: Images/form_validators_email.png + :alt: In the Inspector - Settings of the 'Email' validator. + + In the Inspector - Settings of the 'Email' validator. + + +.. _validators-integer-number: + +Integer number +============== + +The validator checks whether an entered value is a **valid integer**. Numbers +with commas are not allowed. The settings of the validator are as +follows: + +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` + +.. figure:: Images/form_validators_integerNumber.png + :alt: In the Inspector - settings of the validator 'Integer number'. + + In the Inspector - settings of the validator 'Integer number'. + + +.. _validators-floating-point-number: + +Floating-point number +===================== + +The validator checks whether an entered value is a **valid floating-point +number**. Only numbers with commas can be entered. The settings of the +validator are as follows: + +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` + +.. figure:: Images/form_validators_floatingPointNumber.png + :alt: In the Inspector - Settings of the 'Floating-point number' + validator. + + In the Inspector - Settings of the 'Floating-point number' validator. + + +.. _validators-number: + +Number +====== + +The validator checks whether the entered value is a **valid number**. Numbers with +commas are not allowed. The settings of the validator are as +follows: + +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Number"` (validator is + automatically active) + +.. figure:: Images/form_validators_number.png + :alt: In the Inspector - Settings of the 'Number' validator. + + In the Inspector - Settings of the 'Number' validator. + + +.. _validators-number-range: + +Number range +============ + +The validator checks if an entered number is within a +**specified number range**. The settings of the validator are as follows: + +- **Minimum**: The minimum value that can be accepted. +- **Maximum**: The maximum value that can be accepted. +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` +- :ref:`"Number"` + +.. figure:: Images/form_validators_numberRange.png + :alt: In the Inspector - Settings of the 'Number range' validator. + + In the Inspector - Settings of the 'Number range' validator. + + +.. _validators-regular-expression: + +Regular expression +================== + +The validator checks whether an **entered value** matches a +**specific regular expression**. The settings of the validator are as follows: + +- **Regular expression**: The regular expression used for validation. +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +Imagine that you want users to specify a domain name. The +resulting value of the field should contain only the domain, for example, "docs.typo3.org" +instead of "https://docs.typo3.org". The regular expression for this +would be **/^[a-z]+.[a-z]+.[a-z]$/**. + +**The validator is available for the following form elements**: + +- :ref:`"Text"` +- :ref:`"Textarea"` +- :ref:`"Password"` +- :ref:`"Advanced password"` +- :ref:`"Telephone number"` +- :ref:`"URL"` + +.. figure:: Images/form_validators_regularExpression.png + :alt: In the Inspector - Settings of the 'Regular Expression' validator. + + In the Inspector - Settings of the 'Regular Expression' validator. + + +.. _validators-date-range: + +Date range +========== + +This validator checks whether an entered value is within a specific +**date range**. The range can be defined by specifying a **start** and/ or +**end date**. The settings of the validator are as follows: + +- **Start date**: The beginning of the date range (input: YYYY-MM-DD). +- **End date**: The end of the date range (input: YYYY-MM-DD). +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Date"` + +.. figure:: Images/form_validators_dateRange.png + :alt: In the Inspector - Settings of the 'Date range' validator. + + In the Inspector - Settings of the 'Date range' validator. + + +.. _validators-number-of-submitted-values: + +Number of submitted values +========================== + +The validator checks whether an entered value contains a specific number of +elements. The settings of the validator are as follows: + +- **Minimum**: The minimum number of values submitted. +- **Maximum**: The maximum number of submitted values. +- **Custom error message**: Custom error message that will be shown if the + validation fails. + +**The validator is available for the following form elements**: + +- :ref:`"Multi checkbox"` +- :ref:`"Multi select"` + +.. figure:: Images/form_validators_numberOfSubmittedValues.png + :alt: In the Inspector - Settings of the validator 'Number of + submitted values'. + + In the Inspector - Settings of the validator'Number of submitted values'. + + +.. _validators-file-size: + +File size +========= + +The validator checks the file size of a **file resource**. The settings of the +validator are as follows: + +- **Minimum**: The minimum acceptable file size (default: 0B). +- **Maximum**: The maximum acceptable file size (default: 10M). + +Use the format **B | K | M | G** (byte | kilobyte | megabyte | gigabyte) when +entering file sizes. For example: **10M** means **10 megabytes**. Please note +that the maximum file size also depends on the settings of your server +environment. + +**The validator is available for the following form elements**: + +- :ref:`"File upload"` +- :ref:`"Image upload"` + +.. figure:: Images/form_validators_fileSize.png + :alt: In the Inspector - Settings of the 'File size' validator. + + In the Inspector - Settings of the 'File size' validator. + + +.. _validators-date-time: + +Date/ Time +========== + +The validator checks if an entered value is a valid **date and/ or time**. +The settings of the validator are as follows: + +- **Custom error message**: Custom error message that will be shown if the + validation fails. diff --git a/Documentation/I/Concepts/Autocomplete/Index.rst b/Documentation/I/Concepts/Autocomplete/Index.rst new file mode 100644 index 0000000..c3e2d78 --- /dev/null +++ b/Documentation/I/Concepts/Autocomplete/Index.rst @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +.. _concepts-autocomplete: + +============ +Autocomplete +============ + +The :guilabel:`Autocomplete` select in the form editor can be used to +define :html:`autocomplete` properties for input fields. This extension +predefines the most common of the input purposes that are widely +recognized by assistive technologies and +`recommended by the W3C `__. The +HTML standard allows arbitrary values. + +If you need to provide additional fields, you can reconfigure the autocomplete +field with additional select options: + +.. _concepts-autocomplete-add-options: + +Add Autocomplete options to the backend editor +============================================== + +Create a form set in your extension and add a :file:`config.yaml` with the +additional autocomplete options. The file is auto-discovered — no PHP or +TypoScript registration is required. + +.. code-block:: none + :caption: Required directory layout + + EXT:my_sitepackage/ + Configuration/ + Form/ + SitePackage/ + config.yaml + +.. literalinclude:: _config.yaml + :language: yaml + :caption: EXT:my_sitepackage/Configuration/Form/SitePackage/config.yaml diff --git a/Documentation/I/Concepts/Autocomplete/_CustomFormSetupAutoCompleteOption.yaml b/Documentation/I/Concepts/Autocomplete/_CustomFormSetupAutoCompleteOption.yaml new file mode 100644 index 0000000..34e5a65 --- /dev/null +++ b/Documentation/I/Concepts/Autocomplete/_CustomFormSetupAutoCompleteOption.yaml @@ -0,0 +1,12 @@ +prototypes: + standard: + formElementsDefinition: + Text: + formEditor: + editors: + 600: + selectOptions: + # Choose an index that is not in use yet + 12345: + value: 'cc-name' + label: 'cc-name - Full name as given on the payment instrument' diff --git a/Documentation/I/Concepts/Autocomplete/_config.yaml b/Documentation/I/Concepts/Autocomplete/_config.yaml new file mode 100644 index 0000000..fa4c2ce --- /dev/null +++ b/Documentation/I/Concepts/Autocomplete/_config.yaml @@ -0,0 +1,17 @@ +name: my-sitepackage/form +label: 'My Sitepackage — Form Configuration' +priority: 200 + +prototypes: + standard: + formElementsDefinition: + Text: + formEditor: + editors: + 600: + selectOptions: + # Choose an index that is not in use yet + 12345: + value: 'cc-name' + label: 'cc-name - Full name as given on the payment instrument' + diff --git a/Documentation/I/Concepts/Configuration/Index.rst b/Documentation/I/Concepts/Configuration/Index.rst new file mode 100644 index 0000000..28de24c --- /dev/null +++ b/Documentation/I/Concepts/Configuration/Index.rst @@ -0,0 +1,379 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-configuration: + +Configuration +============= + + +.. _concepts-configuration-whysomuchconfiguration: + +A lot of configuration. Why? +---------------------------- + +Building forms in a declarative and programmatic way is complex. Dynamic forms need +program code that is as generic as possible. But generic +program code means a lot of configurative overhead. + +Having so much configuration may seem overwhelming, but it has a lot of +advantages. Many aspects of EXT:form can be manipulated purely +by configuration and without having to involve a developer. + +The configuration in EXT:form is mainly located in places which make sense to a +user. However, this means that certain settings have to be +defined in multiple places in order to avoid unpredictable behaviour. There is +no magic in the form framework - it is all about configuration. + + +.. _concepts-configuration-whyyaml: + +Why YAML? +--------- + +Previous versions of EXT:form used a subset of TypoScript to describe form definitions and +form element behavior. This led to a lot of confusion among integrators because the +definition language looked like TypoScript but did not behave +like TypoScript. + +Form and form element definitions had to be declarative, so YAML was chosen as it is +a declarative language. + +.. _concepts-configuration-yamlregistration: + +YAML registration +----------------- + +YAML configuration files are discovered automatically — no PHP or TypoScript +registration is required. + +Place your YAML files in :file:`EXT:my_extension/Configuration/Form//` and +add a :file:`config.yaml` with a unique set name. TYPO3 scans all active +extensions and loads the files automatically for both frontend and backend. + +.. tip:: + + For debugging purposes or to get an overview of the configuration + use the :guilabel:`System > Configuration` module. Select + the :guilabel:`Form: YAML Configuration` item in the menu to display + parsed YAML form setup. Make sure you have the lowlevel + system extension installed. + +.. tip:: + + We recommend using a `site package `_. + This will make your life easier if you need to do a lot of customization of EXT:form. + + +.. _concepts-configuration-yaml-autodiscovery: +.. _concepts-configuration-yamlregistration-frontend: +.. _concepts-configuration-yamlregistration-backend: +.. _concepts-configuration-yamlregistration-backend-addtyposcriptsetup: + +Auto-discovery directory convention +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: none + + EXT:my_extension/ + Configuration/ + Form/ + MyFormSet/ + config.yaml + +The sub-directory name (``MyFormSet``) is arbitrary. An extension may ship +multiple sets in separate sub-directories. + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Form/MyFormSet/config.yaml + + name: my-vendor/my-form-set + label: 'My Custom Form Set' + # Load order: lower = loaded first. Core base set uses priority 10. + # Extension sets should use > 10 (default: 100) to overlay the base. + priority: 200 + + # Form configuration goes directly below the metadata: + persistenceManager: + allowedExtensionPaths: + 10: 'EXT:my_extension/Resources/Private/Forms/' + + +.. _concepts-configuration-yamlloading: + +YAML loading +------------ + +TYPO3 uses a ':ref:`YAML loader`' for handling +YAML, based on the Symfony YAML package. This YAML loader is able to resolve +environment variables. In addition, EXT:form comes with its own YAML loader, but it +has some restrictions, especially when resolving environment +variables. This is for security reasons. + +EXT:form differentiates between :ref:`form configuration and form definition`. +A form definition can be :ref:`stored` +in the file system (FAL) or can be shipped with an extension. The type of YAML loader +used depends on the setup. + +.. t3-field-list-table:: + :header-rows: 1 + + - :a: YAML file + :b: YAML loader + + - :a: YAML configuration + :b: TYPO3 core + + - :a: YAML definition stored in file system (default when using the ``form editor``) + :b: TYPO3 Form Framework + + - :a: YAML definition stored in an extension + :b: TYPO3 core + + +.. _concepts-configuration-configurationaspects: + +Configuration aspects +--------------------- + +Four things can be configured in EXT:form: + +- frontend rendering, +- the ``form editor``, +- the ``form manager``, and +- the ``form plugin``. + +All configuration is placed in a single :file:`config.yaml` per form set and +is loaded for both frontend and backend. It is up to you whether you want to +keep all configuration in one set or spread it across multiple form sets with +different priorities. + + +.. _concepts-configuration-inheritances: + +Inheritance +----------- + +The final YAML configuration does not produce one huge file. Instead, it is +a sequential compilation process: + +- Registered configuration files are parsed as YAML and + are combined according to their order. +- Finally, all configuration entries with a value of ``null`` are deleted. + +Instead of inheritance, you can also extend/override the frontend configuration +using TypoScript: + +.. code-block:: typoscript + + plugin.tx_form { + settings { + yamlSettingsOverrides { + ... + } + } + } + +.. note:: + + TypoScript overrides like this are ignored by the backend ``form editor``. + +.. note:: + + This process makes life easier. If you are working + with your :ref:`own configuration files `, + you only have to define things that are different to what was in the previously + loaded configuration files. + +An example of overriding the EXT:form Fluid templates. Place the configuration +in :file:`EXT:my_site_package/Configuration/Form/SitePackage/config.yaml` +(auto-discovered, no PHP or TypoScript registration required): + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + templateRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Templates/Form/Frontend/' + partialRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Partials/Form/Frontend/' + layoutRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Layouts/Form/Frontend/' + +The values in your own configuration file will be merged on top of the EXT:form +base set (:file:`EXT:form/Configuration/Form/Base/config.yaml`). + +.. _concepts-configuration-prevent-duplication: + +Prevent duplication +^^^^^^^^^^^^^^^^^^^ + +You can avoid duplication in your YAML files by using anchors (&), aliases (*) and overrides (<<:). + +.. code-block:: yaml + + customEditor: &customEditor + 1761226183: + identifier: custom + templateName: Inspector-TextEditor + label: Custom editor + propertyPath: custom + + otherCustomEditor: &otherCustomEditor + identifier: otherCustom + templateName: Inspector-TextEditor + label: Other custom editor + propertyPath: otherCustom + + prototypes: + standard: + formElementsDefinition: + Text: + formEditor: + editors: + <<: *customEditor + 1761226184: *otherCustomEditor + + +.. _concepts-configuration-placeholders: + +Referencing values with placeholders +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In addition to anchors and aliases, the TYPO3 YAML loader supports ``%...%`` +placeholders. Unlike anchors, they work *across* imported files, because they +are resolved *after* all files have been parsed and merged. + +A placeholder is a dot-separated path into the merged configuration. The +referenced value is looked up and substituted: + +``%path.to.value%`` + +How the result is inserted depends on where the placeholder is used: + +* **Whole value** – if the placeholder is the *only* content of a value, it is + replaced by the referenced value as-is. This may be a scalar **or a complete + array/subtree**. + +* **Inside a string** – if the placeholder is embedded in a larger string, the + referenced value must be scalar (string or numeric) and is interpolated. + +Placeholders can be nested and are resolved recursively. If a referenced path +does not exist, the placeholder is left unchanged. + +Reusing a single value from an existing form element works the same way – here +the new ``CustomText`` element takes over the label of the core ``Text`` +element: + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + CustomText: + formEditor: + label: '%prototypes.standard.formElementsDefinition.Text.formEditor.label%' + + +.. _concepts-configuration-inherit-across-files: + +Inheriting a complete element across files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Because a whole-value placeholder substitutes a complete subtree, it can be used +to base a new form element on the complete configuration of an existing (core) element and +override only a few properties. + +A placeholder is resolved *after* parsing and replaces a whole value. The +inheritance and the overrides therefore live in two files: the imported file +copies the complete element subtree, the importing file merges its overrides on +top. + +Imported file, copies the whole ``Text`` element to ``CustomText``: + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Form/CustomElement/CustomTextInherit.yaml + + imports: + - { resource: 'EXT:form/Configuration/Form/Base/FormElements/Text.yaml' } + + prototypes: + standard: + formElementsDefinition: + CustomText: '%prototypes.standard.formElementsDefinition.Text%' + +Importing file, overrides only single properties: + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Form/CustomElement/config.yaml + + imports: + - { resource: 'EXT:my_extension/Configuration/Form/CustomElement/CustomTextInherit.yaml' } + + prototypes: + standard: + formElementsDefinition: + CustomText: + formEditor: + label: 'Custom Text' + group: custom + iconIdentifier: form-text + +``CustomText`` now inherits the complete configuration of the core ``Text`` +element, while only the listed properties are overridden. + + +.. _concepts-configuration-prototypes: + +Prototypes +---------- + +Most of the form framework configuration is defined +in ``prototypes``. ``standard`` is the default prototype in EXT:form. Prototypes +contain form element definitions - including frontend rendering, ``form editor`` +and ``form plugin``. When you create a new form, your form *definition* references +a prototype *configuration*. + +This allows you to do a lot of clever stuff. For example: + +- depending on which prototype is referenced, the same form can load different + + - ...templates + - ...``form editor`` configurations + - ...``form plugin`` finisher overrides + +- in the ``form manager``, depending on the selected prototype + + - ...different ``form editor`` configurations can be loaded + - ...different pre-configured form templates (boilerplates) can be chosen + +- prototypes can define different/ extended form elements and + display them in the frontend/ ``form editor`` + +The following use case illustrates the prototype concept. Imagine that two +prototypes are defined: "noob" and +"poweruser". + +.. t3-field-list-table:: + :header-rows: 1 + + - :a: + :b: Prototype "noob" + :c: Prototype "poweruser" + + - :a: **Form elements in the ``form editor``** + :b: Just Text, Textarea + :c: No changes. Default behaviour. + + - :a: **Finisher in the ``form editor``** + :b: Only the email finisher is available. It has a field for setting + the subject of the email. The rest of the fields are hidden and filled + with default values. + :c: No changes. Default behaviour. + + - :a: **Finisher overrides in the ``form plugin``** + :b: It is not possible to override the finisher configuration. + :c: No changes. Default behaviour. diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/Index.rst b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/Index.rst new file mode 100644 index 0000000..f9bc9e4 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/Index.rst @@ -0,0 +1,268 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-customfinisherimplementations: + +=============== +Custom finisher +=============== + +.. include:: /Includes/_NoteFinisher.rst + +.. contents:: Table of contents + :local: + +.. _concepts-finishers-custom-howtowrite: + +Write a custom finisher +======================= + +To make your finisher configurable by users in the backend form editor, see +:ref:`here `. + +Add a new finisher to the form configuration prototype by defining a +`finishersDefinition`. Set the `implementationClassName` property to your new implementation class. + +.. literalinclude:: _codesnippets/_finishersDefinition.yaml + :caption: EXT:my_site_package/Configuration/Form/CustomFormSetup.yaml + +`Register `_ +your custom form definition. + +Add options to your finisher with the `options` property. Options +are default values which can be overridden in the `form definition`. + +.. _concepts-finishers-custom-default-value: + +Define default values +--------------------- + +.. literalinclude:: _codesnippets/_CustomFinisher.yaml + :caption: EXT:my_site_package/Configuration/Form/CustomFormSetup.yaml + +.. _concepts-finishers-custom-option-override: + +Override options using the `form definition` +-------------------------------------------- + +.. literalinclude:: _codesnippets/_my_form.yaml + :caption: public/fileadmin/forms/my_form.yaml + +A finisher must implement :php-short:`TYPO3\CMS\Form\Domain\Finishers\FinisherInterface` +and should extend :php-short:`TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher`. +In doing so, in the logic of the +finisher the method `executeInternal()` will be called first. + +.. _concepts-finishers-customfinisherimplementations-accessingoptions: + +Accessing finisher options +========================== + +If your finisher class extends :php-short:`TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher`, +you can access the option values in the finisher using method `parseOption()`: + +.. code-block:: php + + $yourCustomOption = $this->parseOption('yourCustomOption'); + +`parseOption()` looks for 'yourCustomOption' in your +`form definition`. + +.. literalinclude:: _codesnippets/_CustomFinisher.yaml + :caption: EXT:my_site_package/Classes/Domain/Finishers/CustomFinisher.yaml + +If it can't find it, `parseOption()` checks + +1. for a default value in the `prototype` configuration, + +2. for `$defaultOptions` inside your finisher class: + + + +If it doesn't find anything, `parseOption()` returns `null`. + +If it finds the option, the process checks whether the option value will +access :ref:`FormRuntime values `. +If the `FormRuntime` returns a positive result, it is checked whether the +option value :ref:`can access values of preceding finishers `. +At the end, it :ref:`translates the finisher options `. + +.. _concepts-finishers-customfinisherimplementations-accessingoptions-formruntimeaccessor: + +Accessing form runtime values +============================= + +You can populate finisher options with +submitted form values using the `parseOption()` method. +You can access values of the `FormRuntime` and therefore values in every +form element by encapsulating option values with `{}`. Below, if there is a +form element with the `identifier` 'subject', you can access the value +in the finisher configuration: + +.. literalinclude:: _codesnippets/_my_form_extended.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. code-block:: php + + // $yourCustomOption contains the value of the form element with the + // identifier 'subject' + $yourCustomOption = $this->parseOption('yourCustomOption'); + +You can use `{__currentTimestamp}` as an option value to return the +current UNIX timestamp. + +.. _concepts-finishers-customfinisherimplementations-finishercontext: + +Finisher Context +================ + +The :php-short:`TYPO3\CMS\Form\Domain\Finishers\FinisherContext` class takes care of +transferring a finisher context to each finisher. If your finisher class extends +:php-short:`TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher` the +finisher context will be available via: + +.. code-block:: php + + $this->finisherContext + +The `cancel` method prevents the execution of successive finishers: + +.. code-block:: php + + $this->finisherContext->cancel(); + +The method `getFormValues` returns the submitted form values. + +.. code-block:: php + + $this->finisherContext->getFormValues(); + +The method `getFormRuntime` returns the `FormRuntime`: + +.. code-block:: php + + $this->finisherContext->getFormRuntime(); + +.. _concepts-finishers-customfinisherimplementations-finishercontext-sharedatabetweenfinishers: + +Share data between finishers +============================ + +The method `getFinisherVariableProvider` returns an +object (:php-short:`TYPO3\CMS\Form\Domain\Finishers\FinisherVariableProvider`) which allows you +to store data and transfer it to other finishers. The data +can be easily accessed programmatically or inside your configuration: + +.. code-block:: php + + $this->finisherContext->getFinisherVariableProvider(); + +The data is stored in :php-short:`TYPO3\CMS\Form\Domain\Finishers\FinisherVariableProvider` and is accessed +by a user-defined 'finisher identifier' and a custom option value path. The +name of the 'finisher identifier' should consist of the name of the finisher +without the 'Finisher' appendix. If your finisher class extends +:php-short:`TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher`, the finisher +identifier name is stored in the following variable: + +.. code-block:: php + + $this->shortFinisherIdentifier + +For example, if the name of your finisher class is 'CustomFinisher', this +variable will contain 'Custom'. + +There are 4 methods to access and manage data in the `FinisherVariableProvider`: + +* Add data: + + .. code-block:: php + + $this->finisherContext->getFinisherVariableProvider()->add( + $this->shortFinisherIdentifier, + 'unique.value.identifier', + $value + ); + +* Get data: + + .. code-block:: php + + $this->finisherContext->getFinisherVariableProvider()->get( + $this->shortFinisherIdentifier, + 'unique.value.identifier', + 'default value' + ); + +* Check the existence of data: + + .. code-block:: php + + $this->finisherContext->getFinisherVariableProvider()->exists( + $this->shortFinisherIdentifier, + 'unique.value.identifier' + ); + +* Delete data: + + .. code-block:: php + + $this->finisherContext->getFinisherVariableProvider()->remove( + $this->shortFinisherIdentifier, + 'unique.value.identifier' + ); + +In this way, finishers can access `FinisherVariableProvider` data programmatically. +However, it is also possible to access `FinisherVariableProvider` data using form configuration. + +Assuming that a finisher called 'Custom' adds data to a `FinisherVariableProvider`: + +.. code-block:: php + + $this->finisherContext->getFinisherVariableProvider()->add( + $this->shortFinisherIdentifier, + 'unique.value.identifier', + 'Wouter' + ); + +other finishers can access the value 'Wouter' by setting +`{Custom.unique.value.identifier}` in the form definition file. + + +.. literalinclude:: _codesnippets/_my_form_custom.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _concepts-finishers-customfinisherimplementations-extend-gui: + +Add finisher to backend UI +========================== + +After registering a new finisher in the yaml form definition file, you can also +add it to the backend form editor for your backend users ( `formEditor:` +section below) to work with in the GUI: + +.. literalinclude:: _codesnippets/_backend-ui.yaml + :caption: EXT:my_site_package/Configuration/Form/CustomFormSetup.yaml + :linenos: + +.. important:: + + Make sure to define an `iconIdentifier` in the `finishersDefinition` of your + finisher, otherwise the button to remove the finisher from the + form will not be visible. + +.. _concepts-finishers-custom-extend-gui-configuration: + +Configuration registration +-------------------------- + +Place your YAML files in a form set directory — no PHP registration needed: + +.. code-block:: none + + EXT:my_extension/ + Configuration/ + Form/ + MyFinisher/ + config.yaml + +.. seealso:: + + :ref:`concepts-configuration-yaml-autodiscovery` diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.php b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.php new file mode 100644 index 0000000..687b3a4 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.php @@ -0,0 +1,18 @@ + 'Olli', + ]; + + // ... + protected function executeInternal() + { + // TODO: Implement executeInternal() method. + } +} diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.yaml new file mode 100644 index 0000000..7b91423 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_CustomFinisher.yaml @@ -0,0 +1,7 @@ +prototypes: + standard: + finishersDefinition: + CustomFinisher: + implementationClassName: 'MyVendor\MySitePackage\Domain\Finishers\CustomFinisher' + options: + yourCustomOption: 'Ralf' diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_backend-ui.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_backend-ui.yaml new file mode 100644 index 0000000..5fb9d7f --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_backend-ui.yaml @@ -0,0 +1,64 @@ +prototypes: + standard: + formElementsDefinition: + Form: + formEditor: + editors: + 900: + # Extend finisher drop down + selectOptions: + 35: + value: 'CustomFinisher' + label: 'Custom Finisher' + propertyCollections: + finishers: + # add finisher fields + 25: + identifier: 'CustomFinisher' + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: "Custom Finisher" + # custom field (input, required) + 110: + identifier: 'customField' + templateName: 'Inspector-TextEditor' + label: 'Custom Field' + propertyPath: 'options.customField' + propertyValidators: + 10: 'NotEmpty' + # email field + 120: + identifier: 'email' + templateName: 'Inspector-TextEditor' + label: 'Subscribers email' + propertyPath: 'options.email' + enableFormelementSelectionButton: true + propertyValidators: + 10: 'NotEmpty' + 20: 'FormElementIdentifierWithinCurlyBracesInclusive' + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + finishersDefinition: + CustomFinisher: + formEditor: + iconIdentifier: 'form-finisher' + label: 'Custom Finisher' + predefinedDefaults: + options: + customField: '' + email: '' + # displayed when overriding finisher settings + FormEngine: + label: 'Custom Finisher' + elements: + customField: + label: 'Custom Field' + config: + type: 'text' + email: + label: 'Subscribers email' + config: + type: 'text' diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_finishersDefinition.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_finishersDefinition.yaml new file mode 100644 index 0000000..8523595 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_finishersDefinition.yaml @@ -0,0 +1,6 @@ +prototypes: + standard: + finishersDefinition: + CustomFinisher: + implementationClassName: 'MyVendor\MySitePackage\Domain\Finishers\CustomFinisher' + diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form.yaml new file mode 100644 index 0000000..d41c036 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form.yaml @@ -0,0 +1,13 @@ +identifier: sample-form +label: 'Simple Contact Form' +prototype: standard +type: Form + +finishers: + - + identifier: CustomFinisher + options: + yourCustomOption: 'Björn' + +renderables: + # ... diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_custom.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_custom.yaml new file mode 100644 index 0000000..1a3b601 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_custom.yaml @@ -0,0 +1,15 @@ +identifier: sample-form +label: 'Simple Contact Form' +prototype: standard +type: Form + +finishers: + - + identifier: Custom + options: + yourCustomOption: 'Frans' + + - + identifier: SomeOtherStuff + options: + someOtherCustomOption: '{Custom.unique.value.identifier}' diff --git a/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_extended.yaml b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_extended.yaml new file mode 100644 index 0000000..38f39f8 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/CustomFinisherImplementations/_codesnippets/_my_form_extended.yaml @@ -0,0 +1,16 @@ +identifier: simple-contact-form +label: 'Simple Contact Form' +prototype: standard +type: Form + +finishers: + - + identifier: Custom + options: + yourCustomOption: '{subject}' + +renderables: + - + identifier: subject + label: 'Subject' + type: Text diff --git a/Documentation/I/Concepts/Finishers/Index.rst b/Documentation/I/Concepts/Finishers/Index.rst new file mode 100644 index 0000000..48c99a5 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/Index.rst @@ -0,0 +1,40 @@ +:navigation-title: Finishers + +.. include:: /Includes.rst.txt +.. _concepts-finishers: + +============================================ +Finishers: post-submission actions for forms +============================================ + +When a form has been submitted in TYPO3, finishers decide what happens +next - sending an email, redirecting to another page, or showing a +confirmation message. This page gives you a quick tour of built-in finishers. +For more details, see :ref:`Finisher Options `. + +There is also a dedicated chapter on +:ref:`translations of finisher options `. + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + ReadyToUseFinishers/Index + CustomFinisherImplementations/Index + +.. _concepts-finishers-execution-order: + +Finisher execution order +======================== + +.. important:: + Finishers are executed in the order that is defined in your form definition. The + `Redirect finisher `_ + terminates all finishers. + +If you are using the `redirect finisher `_, make sure it is the last finisher +that is executed. The redirect finisher stops the +execution of all subsequent finishers in order to perform a redirect. Finishers +that are defined after a redirect finisher will be ignored. + +.. literalinclude:: ReadyToUseFinishers/RedirectFinisher/_codesnippets/_example-redirect.yaml diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/Index.rst new file mode 100644 index 0000000..cb19fde --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/Index.rst @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-closurefinisher: + +================ +Closure finisher +================ + +The "Closure finisher" can only be used in programmatically-created forms. It allows +you to execute your own finisher code without implementing/ declaring a finisher. + +.. contents:: Table of contents + +.. include:: /Includes/_NoteFinisher.rst + +.. _apireference-finisheroptions-closurefinisher-options: + +Closure finisher option +======================= + +.. _apireference-finisheroptions-closurefinisher-options-closure: + +.. confval:: closure + :name: closurefinisher-closure + :required: true + :type: `?\Closure` + :default: `null` + + The name of the field as shown in the form. + +.. _apireference-finisheroptions-closurefinisher: + +Using the closure finisher programmatically +=========================================== + +This finisher can only be used in programmatically-created forms. It allows +you to execute your own finisher code without implementing/ declaring a finisher. + +Code example: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\ClosureFinisher`. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..d719cde --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ClosureFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,20 @@ +setOption('closure', function ($finisherContext) + { + $formRuntime = $finisherContext->getFormRuntime(); + // ... + }); + $formDefinition->addFinisher($closureFinisher); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/Index.rst new file mode 100644 index 0000000..c90678d --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/Index.rst @@ -0,0 +1,109 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-confirmationfinisher: +.. _finishers-confirmation-message: + +===================== +Confirmation finisher +===================== + +A basic finisher that outputs a text or content element. + +.. contents:: Table of contents + +.. include:: /Includes/_NoteFinisher.rst + +.. _apireference-finisheroptions-confirmationfinisher-options: + +Confirmation finisher options +============================= + +This finisher outputs a text or a content element after the form has been submitted. + +The settings of the finisher are: + +.. _apireference-finisheroptions-confirmationfinisher-options-message: + +.. confval:: message + :name: confirmationfinisher-message + :type: string + :default: `The form has been submitted.` + + Displays this text if the `contentElementUid` is not set. + +.. confval:: contentElementUid + :name: confirmationfinisher-contentElementUid + :type: int + :default: 0 + + Renders the content element with the supplied ID. + +.. confval:: translation.propertiesExcludedFromTranslation + :name: confirmationfinisher-translation-propertiesExcludedFromTranslation + :type: array + :default: `[]` + + Defines a list of finisher option properties that should be excluded from + translation. + + When specified, the listed properties are not processed by the + :php-short:`\TYPO3\CMS\Form\Service\TranslationService` during translation + of finisher options. This prevents their values from being replaced by + translated equivalents, even if translations exist for those options. + + This option is usually generated automatically as soon as FlexForm overrides + are in place and normally does not need to be set manually in the form + definition. + + See `Skip translation of overridden form finisher options `_ + for an example. + +.. _concepts-finishers-confirmationfinisher-yaml: + +Confirmation finisher in the YAML form definition +================================================= + +A basic finisher that outputs text or a content element. + +Outputs text ``message``: + +.. literalinclude:: _codesnippets/_form_with_confirmation_finisher.yaml + :caption: public/fileadmin/forms/my_form.yaml + +Outputs content element with id 42: + +.. literalinclude:: _codesnippets/_form_with_confirmation_content_element.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _concepts-finishers-confirmationfinisher-yaml-propertiesExcludedFromTranslation: + +Skip translation of overridden form finisher options +==================================================== + +The following is an example of the `translation.propertiesExcludedFromTranslation `_ +option being used to exclude three properties (subject, recipients and +format) from translation. + +Using this translation option, the properties can only be overridden by a FlexForm, not by the +:php-short:`\TYPO3\CMS\Form\Service\TranslationService`. + +This option is automatically generated as soon as FlexForm overrides are in place. + +The following syntax is only documented for completeness. Nonetheless, it can +also be added to a form definition YAML file. + +.. literalinclude:: _codesnippets/_form_with_propertiesExcludedFromTranslation.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _apireference-finisheroptions-confirmationfinisher: + +Using the confirmation finisher in PHP code +=========================================== + +Developers can use the finisher key `Confirmation` to create +confirmation finishers in their own classes: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +Th confirmation finisher is implemented in +:php:`TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher`. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..fab31ad --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,19 @@ +createFinisher('Confirmation', [ + 'message' => $message, + ]); + } + private function addConfirmationnFinisherWithContentElement(FormDefinition $formDefinition, int $contentElementUid) + { + $formDefinition->createFinisher('Confirmation', [ + 'contentElementUid' => $contentElementUid, + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_content_element.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_content_element.yaml new file mode 100644 index 0000000..2114b63 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_content_element.yaml @@ -0,0 +1,10 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: Confirmation + options: + contentElementUid: 42 + #... diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_finisher.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_finisher.yaml new file mode 100644 index 0000000..e343b0c --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_confirmation_finisher.yaml @@ -0,0 +1,10 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: Confirmation + options: + message: 'Thx for using TYPO3' + # ... diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_propertiesExcludedFromTranslation.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_propertiesExcludedFromTranslation.yaml new file mode 100644 index 0000000..43bd226 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/ConfirmationFinisher/_codesnippets/_form_with_propertiesExcludedFromTranslation.yaml @@ -0,0 +1,17 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + options: + identifier: EmailToSender + subject: 'Email to sender' + recipients: + recipient@example.org: 'Some Name' + translation: + propertiesExcludedFromTranslation: + - subject + - recipients + - format + # ... diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/Index.rst new file mode 100644 index 0000000..6e05a11 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/Index.rst @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-deleteuploadsfinisher: +.. _finishers-delete-uploads: + +======================= +DeleteUploads finishers +======================= + +The "DeleteUploads finisher" removes files that have been submitted. You can use this +finisher after the email finisher if you do not want to keep the files +in your TYPO3 installation. + +.. note:: + + Finishers are only executed when a form is successfully submitted. If a user uploads + a file but does not finish filling out the form, the uploaded files will not + be deleted. + +.. contents:: Table of contents + +.. include:: /Includes/_NoteFinisher.rst + +.. _concepts-finishers-deleteuploadsfinisher-yaml: + +DeleteUploads finisher in the YAML form definition +================================================== + +Use this finisher after the email finisher if you do not want to keep the files +in your TYPO3 installation. + +Finishers are executed in the order they are listed in the form definition +YAML file: + +.. literalinclude:: _codesnippets/_form.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _apireference-finisheroptions-deleteuploadsfinisher: + +Using the DeleteUploads finisher in PHP code +============================================ + +Developers can use the finisher key `DeleteUploads` to create +deleteuploads finishers in their own classes: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\DeleteUploadsFinisher`. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..4416c8a --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,11 @@ +createFinisher('DeleteUploads'); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_form.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_form.yaml new file mode 100644 index 0000000..3e8b2fe --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/DeleteUploadsFinisher/_codesnippets/_form.yaml @@ -0,0 +1,13 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: EmailToSender + options: + subject: 'Your Message: {message}' + - + identifier: DeleteUploads + # Define the delete uploads finisher AFTER the email finisher +# ... diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/Index.rst new file mode 100644 index 0000000..cf0ecdd --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/Index.rst @@ -0,0 +1,325 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-emailfinisher: + +============== +Email finisher +============== + +The EmailFinisher sends an email to one recipient. EXT:form has two +EmailFinishers with the identifiers EmailToReceiver and EmailToSender. + +.. contents:: Table of contents + +.. include:: /Includes/_NoteFinisher.rst + + +.. _concepts-finishers-emailfinisher-backend: +.. _finishers-email-to-sender: +.. _finishers-email-to-receiver: + +Using email finishers in the backend form editor +================================================ + +Editors can use two email finishers in the backend form editor: + +Email to sender (form submitter) + This finisher sends an email with the contents of the form to the user + submitting the form . + +Email to receiver (you) + This finisher sends an email with the contents of the form to the owner of the + website. The settings of this finisher are the + same as the "Email to sender" finisher + +.. _apireference-finisheroptions-emailfinisher-options: + +Options of the email finisher +============================= + +.. _apireference-finisheroptions-emailfinisher-options-subject: + +.. confval:: Subject [subject] + :name: emailfinisher-subject + :type: string + :required: true + + Subject of the email. + +.. _apireference-finisheroptions-emailfinisher-options-recipients: + +.. confval:: Recipients [recipients] + :name: emailfinisher-recipients + :type: array + :required: true + + Email addresses and names of the recipients (To). + + **Email Address** + Email address of a recipient, e.g. "some.recipient@example.com" + or "{email-1}". + **Name** + Name of a recipient, e.g. "Some Recipient" or "{text-1}". + +.. _apireference-finisheroptions-emailfinisher-options-senderaddress: + +.. confval:: Sender address [senderAddress] + :name: emailfinisher-senderAddress + :type: string + :required: true + + Email address of the sender, for example "your.company@example.org". + + If `smtp `_ + is used, this email address needs to be allowed by the + SMTP server. Use `replyToRecipients` if you want to enable the receiver to + reply to the message. + +.. _apireference-finisheroptions-emailfinisher-options-sendername: + +.. confval:: Sender name [senderName] + :name: emailfinisher-senderName + :type: string + :default: `''` + + Name of the sender, for example "Your Company". + +.. _apireference-finisheroptions-emailfinisher-options-replytorecipients: + +.. confval:: Reply-to Recipients [replyToRecipients] + :name: emailfinisher-replyToRecipients + :type: array + :default: `[]` + + Email address which will be used when someone replies to the email. + + **Email Address**: + Email address for reply-to. + **Name** + Name for reply-to. + +.. _apireference-finisheroptions-emailfinisher-options-carboncopyrecipients: + +.. confval:: CC Recipient [carbonCopyRecipients] + :name: emailfinisher-carbonCopyRecipients + :type: array + :default: `[]` + + Email address to which a copy of the email is sent. The information is + visible to all other recipients. + + **Email Address**: + Email address for CC. + **Name** + Name for CC. + +.. _apireference-finisheroptions-emailfinisher-options-blindcarboncopyrecipients: + +.. confval:: BCC Recipients [blindCarbonCopyRecipients] + :name: emailfinisher-blindCarbonCopyRecipients + :type: array + :default: `[]` + + Email address to which a copy of the email is sent. The information is not + visible to any of the recipients. + + **Email Address**: + Email address for BCC. + **Name** + Name for BCC. + +.. _apireference-finisheroptions-emailfinisher-options-addhtmlpart: + +.. confval:: Add HTML part [addHtmlPart] + :name: emailfinisher-addHtmlPart + :type: bool + :default: `true` + + If set, emails will contain plaintext and HTML, otherwise only plaintext. + In this way, HTML can be disabled and plaintext-only emails enforced. + +.. _apireference-finisheroptions-emailfinisher-options-attachuploads: + +.. confval:: Attach uploads [attachUploads] + :name: emailfinisher-attachUploads + :type: bool + :default: `true` + + If set, all uploaded items are attached to the email. + +.. _apireference-finisheroptions-emailfinisher-options-title: + +.. confval:: Title [title] + :name: emailfinisher-title + :type: string + :required: false + :default: `undefined` + + The title shown in the email. + +.. _apireference-finisheroptions-emailfinisher-options-translation-language: + +.. confval:: Translation language [translation.language] + :name: emailfinisher-translation-language + :type: string + :required: false + :default: `undefined` + + If not set, the finisher options are translated depending on the current + frontend language (if translations exist). This option allows you to force + translations for a given language isocode, e.g. `da` or `de`. + See :ref:`Translate finisher options`. + +.. _apireference-finisheroptions-emailfinisher-options-options: + +Additional email finisher options +================================= + +Additional options can be set in the form definition YAML and +programmatically in the options array but **not** in the backend editor: + +.. _apireference-finisheroptions-emailfinisher-options-translation-propertiesExcludedFromTranslation: + +.. confval:: Properties excluded from translation [translation.propertiesExcludedFromTranslation] + :name: emailfinisher-translation-propertiesExcludedFromTranslation + :type: array + :required: false + :default: `undefined` + + If not set, the finisher options are translated depending on the current frontend language (if translations exists). + This option allows you to force translations for a given language isocode, e.g 'da' or 'de'. + See :ref:`Translate finisher options`. + It will be skipped for all specified finisher options. + +.. _apireference-finisheroptions-emailfinisher-options-translation-translationfiles: + +.. confval:: translation.translationFiles + :name: emailfinisher-translation-translationFiles + :type: array + :required: false + :default: `undefined` + + If set, this translation file(s) will be used for finisher option + translations. If not set, the translation file(s) from the `Form` element + will be used. + Read :ref:`Translate finisher options`. + +.. _apireference-finisheroptions-emailfinisher-options-layoutrootpaths: + +.. confval:: layoutRootPaths + :name: emailfinisher-layoutRootPaths + :type: array + :required: false + :default: `undefined` + + Fluid layout paths. + +.. _apireference-finisheroptions-emailfinisher-options-partialrootpaths: + +.. confval:: partialRootPaths + :name: emailfinisher-partialRootPaths + :type: array + :required: false + :default: `undefined` + + Fluid partial paths. + +.. _apireference-finisheroptions-emailfinisher-options-templaterootpaths: + +.. confval:: templateRootPaths + :name: emailfinisher-templateRootPaths + :type: array + :required: false + :default: `undefined` + + Fluid template paths; all templates get the current :php:`FormRuntime` + assigned as :code:`form` and the :php:`FinisherVariableProvider` assigned + as :code:`finisherVariableProvider`. + +.. _apireference-finisheroptions-emailfinisher-options-variables: + +.. confval:: variables + :name: emailfinisher-variables + :type: array + :required: false + :default: `undefined` + + Associative array of variables which are available inside the Fluid template. + +.. _concepts-finishers-emailfinisher-yaml: + +Email finishers in the YAML form definition +=========================================== + +This finisher sends an email to one recipient. +EXT:form has two email finishers with identifiers +`EmailToReceiver` and `EmailToSender`. + +.. literalinclude:: _codesnippets/_form.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _apireference-finisheroptions-emailfinisher: + +Using Email finishers in PHP code +================================= + +Developers can create a confirmation finisher by using the key `EmailToReceiver` +or `EmailToSender`. + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\EmailFinisher`. + +.. _concepts-finishers-emailfinisher-bcc-recipients: + +Working with BCC recipients +=========================== + +Email finishers can work with different recipient types, including Carbon Copy +(CC) and Blind Carbon Copy (BCC). Depending on the configuration of your server +and TYPO3 instance, it may not be possible to send emails to BCC recipients. +The :php:`$GLOBALS['TYPO3_CONF_VARS']['MAIL']['transport_sendmail_command']` +configuration value is important here. As documented in :ref:`CORE API `, +TYPO3 recommends using the parameter :php:`-bs` (instead of :php:`-t -i`) with +:php:`sendmail`. The parameter :php:`-bs` tells TYPO3 to use the SMTP standard +so that BCC recipients are properly set. `Symfony `__ +also mentions the :php:`-t` parameter problem. Since TYPO3 7.5 +(`#65791 `__) +the :php:`transport_sendmail_command` is automatically set from the PHP runtime +configuration and saved. If you have problems sending emails to BCC +recipients, this could be the solution. + +.. _concepts-finishers-emailfinisher-fluidemail: + +About FluidEmail +================ + +.. versionchanged:: 12.0 + The :php:`EmailFinisher` always sends email via :php:`FluidEmail`. + +The FluidEmail finisher allows emails to be sent in a standardized way. + +The finisher has an :yaml:`option` property :yaml:`title` that adds an email title to the default +FluidEmail template. Variables can be used in options using the bracket syntax. +These variables can be overwritten by FlexForm configuration in the form plugin + +Use these options to customize the fluid templates: + +* :yaml:`templateName`: The template name (for both HTML and plaintext, without the + extension) +* :yaml:`templateRootPaths`: The paths to the templates +* :yaml:`partialRootPaths`: The paths to the partials +* :yaml:`layoutRootPaths`: The paths to the layouts + +.. note:: + The field :yaml:`templatePathAndFilename` is no longer evaluated. + +Here is an example finisher configuration: + +.. literalinclude:: _codesnippets/_example-email.yaml + :caption: public/fileadmin/forms/my_form_with_email_finisher.yaml + +These template files must exist: + +* :file:`EXT:my_site_package/Resources/Private/Templates/Email/ContactForm.html` +* :file:`EXT:my_site_package/Resources/Private/Templates/Email/ContactForm.txt` diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_example-email.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_example-email.yaml new file mode 100644 index 0000000..2a49694 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_example-email.yaml @@ -0,0 +1,15 @@ +identifier: contact +type: Form +prototypeName: standard +finishers: + - + identifier: EmailToSender + options: + subject: 'Your Message: {message}' + title: 'Hello {name}, your confirmation' + templateName: ContactForm + templateRootPaths: + 100: 'EXT:my_site_package/Resources/Private/Templates/Email/' + partialRootPaths: + 100: 'EXT:my_site_package/Resources/Private/Partials/Email/' + addHtmlPart: true diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..10ea676 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,19 @@ +createFinisher('EmailToReceiver', [ + 'subject' => 'Your message', + 'recipients' => [ + 'your.company@example.com' => 'Your Company name', + 'ceo@example.com' => 'CEO' + ], + 'senderAddress' => $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromAddress'], + 'senderName' => $GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName'], + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_form.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_form.yaml new file mode 100644 index 0000000..7a88334 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/EmailFinisher/_codesnippets/_form.yaml @@ -0,0 +1,14 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: EmailToReceiver + options: + subject: 'Your message' + recipients: + your.company@example.com: 'Your Company name' + ceo@example.com: 'CEO' + senderAddress: 'form@example.com' + senderName: 'form submitter' diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/Index.rst new file mode 100644 index 0000000..f2d8313 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/Index.rst @@ -0,0 +1,116 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-flashmessagefinisher: + +===================== +FlashMessage finisher +===================== + +The "FlashMessage finisher" is a basic finisher that adds a message to the +FlashMessageContainer. + +.. contents:: Table of contents + +.. note:: + + This finisher cannot be used in the backend form editor. It can only be used + in a form definition YAML file or programmatically. + +.. include:: /Includes/_NoteFinisher.rst + +.. _apireference-finisheroptions-flashmessagefinisher-options: + +FlashMessage finisher options +============================= + +The following options can be set (in the form definition YAML or +programmatically): + +.. _apireference-finisheroptions-flashmessagefinisher-options-messagebody: + +.. confval:: messageBody + :name: flashmessagefinisher-messageBody + :type: string + :required: true + + The flash message. May contain placeholders like `%s` that + are replaced with `messageArguments`. + +.. _apireference-finisheroptions-flashmessagefinisher-options-messagetitle: + +.. confval:: messageTitle + :name: flashmessagefinisher-messageTitle + :type: string + :default: `''` + + If set, is the flash message title. + +.. _apireference-finisheroptions-flashmessagefinisher-options-messagearguments: + +.. confval:: messageArguments + :name: flashmessagefinisher-messageArguments + :type: array + :default: `[]` + + If `messageBody` contains placeholders (like `%s`), they will be replaced + by these. + +.. _apireference-finisheroptions-flashmessagefinisher-options-messagecode: + +.. confval:: messageCode + :name: flashmessagefinisher-messageCode + :type: ?int + :default: `null` + + A unique code to identify the message. By convention, the + unix time stamp at the time when the message is created is used, + for example `1758455932`. + +.. _apireference-finisheroptions-flashmessagefinisher-options-severity: + +.. confval:: severity + :name: flashmessagefinisher-severity + :type: :php:`\TYPO3\CMS\Core\Type\ContextualFeedbackSeverity` + :default: `ContextualFeedbackSeverity::OK` + + The severity influences the display (color and icon) of the flash message. + +.. confval:: translation.propertiesExcludedFromTranslation + :name: flashmessagefinisher-translation-propertiesExcludedFromTranslation + :type: array + :default: `[]` + + Defines a list of finisher option properties to be excluded from + translation. + + If set, these properties will not be processed by the + :php-short:`\TYPO3\CMS\Form\Service\TranslationService` during translation + of finisher options. This prevents their values from being replaced by + translated equivalents, even if translations exist for those options. + + This option is usually generated automatically as soon as FlexForm overrides + are in place and normally does not need to be set manually in the form + definition. + + See `Skip translation of overridden form finisher options `_ + for an example. + +.. _concepts-finishers-flashmessagefinisher-yaml: + +FlashMessage finisher in a YAML form definition +=============================================== + +.. literalinclude:: _codesnippets/_form.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _apireference-finisheroptions-flashmessagefinisher: + +Using FlashMessage finishers in PHP code +======================================== + +Developers can use the finisher key `FlashMessage` to create +flash message finishers in their own classes: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\FlashMessageFinisher`. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..d17ff71 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,18 @@ +createFinisher('FlashMessage', [ + 'messageTitle' => 'Merci', + 'messageCode' => 201905041245, + 'messageBody' => 'Thx for using %s', + 'messageArguments' => ['TYPO3'], + 'severity' => ContextualFeedbackSeverity::OK, + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_form.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_form.yaml new file mode 100644 index 0000000..a6c2900 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/FlashMessageFinisher/_codesnippets/_form.yaml @@ -0,0 +1,14 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: FlashMessage + options: + messageTitle: 'Merci' + messageCode: 201905041245 + messageBody: 'Thx for using %s' + messageArguments: + - 'TYPO3' + severity: 0 diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/Index.rst new file mode 100644 index 0000000..1e3224b --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/Index.rst @@ -0,0 +1,62 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-ready-to-use: +.. _apireference-finisheroptions: + +====================== +Ready-to-use finishers +====================== + +The TYPO3 Form Framework provides several built-in finishers that can be +used out of the box. These handle common post submission tasks such as +sending emails, showing confirmation messages, and saving data. + +In addition, third-party extensions may provide further finishers, which +can be found in the `TYPO3 Extension Repository (TER) `_. + +.. card-grid:: + :columns: 1 + :columns-md: 2 + :gap: 4 + :class: pb-4 + :card-height: 100 + + .. card:: `Closure finisher `_ + + Executes a custom PHP closure after a successful submission—use + for ad-hoc logic without creating a full class. + + .. card:: `Confirmation finisher `_ + + Renders a confirmation/thank-you message (or view) once the form + is submitted. + + .. card:: `DeleteUploads finisher `_ + + Removes files uploaded during the submission—useful if after + emailing them you don’t want to keep the files on the server. + + .. card:: `Email finisher `_ + + Sends an email with the submitted data; supports Fluid + templates and placeholders for field values. + + .. card:: :doc:`Flash message finisher ` + + Shows a flash message to the user after submit (e.g., success or + info notice). + + .. card:: `Redirect finisher `_ + + Redirects to another page or route after submit; must be last + finisher since it stops subsequent finishers. + + .. card:: `SaveToDatabase finisher `_ + + Persists submitted form values to a database table according to + your mapping/configuration. + +.. toctree:: + :hidden: + :glob: + + */Index diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/Index.rst new file mode 100644 index 0000000..7787102 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/Index.rst @@ -0,0 +1,135 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-redirectfinisher: +.. _finishers-redirect: + +================= +Redirect finisher +================= + +This finisher redirects the user to a particular page after the form has been submitted. +Parameters can be added to the URL. + +.. contents:: Table of contents + +.. important:: + + Finishers are executed in the order defined in your form definition. + This finisher stops the execution of all subsequent finishers in order to perform + the redirect. Therefore, this finisher should always be the last finisher to be + executed. Finishers placed after this one in the form definition will be ignored. + +.. _apireference-finisheroptions-redirectfinisher-options: + +Redirect finisher options +========================= + +.. _apireference-finisheroptions-redirectfinisher-options-pageuid: + +.. confval:: Page: [pageUid] + :name: redirectfinisher-pageUid + :type: int + :required: true + :default: `1` + + ID of the page to redirect to. Button :guilabel:`Page` can be used to select + a page from the page tree. + +.. _apireference-finisheroptions-redirectfinisher-options-additionalparameters: + +.. confval:: Additional parameters: [additionalParameters] + :name: redirectfinisher-additionalParameters + :type: string + :required: false + :default: `''` + + URL parameters which will be appended to the URL. + +.. _apireference-finisheroptions-redirectfinisher-options-fragment: + +.. confval:: URL fragment: [fragment] + :name: redirectfinisher-fragment + :type: string + :required: false + :default: `''` + + ID of a content element identifier or a custom fragment + identifier. This will be appended to the URL and used as section anchor. + + Adds a fragment (e.g. :html:`#c9` or :html:`#foo`) to the redirect link. + The :html:`#` character can be omitted. + +.. _apireference-finisheroptions-redirectfinisher-options-additional: + +Additional redirect finisher options +==================================== + +These options can be set in the form definition YAML or +programmatically in the options array. They cannot be set in the backend form editor: + +.. _apireference-finisheroptions-redirectfinisher-options-delay: + +.. confval:: delay + :name: redirectfinisher-delay + :type: int + :required: false + :default: `0` + + The redirect delay in seconds. + +.. _apireference-finisheroptions-redirectfinisher-options-statuscode: + +.. confval:: statusCode + :name: redirectfinisher-statusCode + :type: int + :required: false + :default: `303` + + The HTTP status code for the redirect. Default is "303 See Other". + +.. confval:: translation.propertiesExcludedFromTranslation + :name: redirectfinisher-translation-propertiesExcludedFromTranslation + :type: array + :default: `[]` + + Defines a list of finisher option properties to be excluded from + translation. + + If set, these properties are not processed by the + :php-short:`\TYPO3\CMS\Form\Service\TranslationService` during translation. + This prevents their values from being replaced by + translated equivalents, even if translations exist for those options. + + This option is usually generated automatically shen FlexForm overrides + are in place and normally does not need to be set manually in the form + definition. + + See `Skip translation of overridden form finisher options `_ + for an example. + +.. _concepts-finishers-redirectfinisher-yaml: + +Redirect finisher in a YAML form definition +=========================================== + +.. literalinclude:: _codesnippets/_form.yaml + :caption: public/fileadmin/forms/my_form.yaml + +.. _concepts-finishers-redirectfinisher-last: + +Example: Load the redirect finisher last +======================================== + +.. literalinclude:: _codesnippets/_example-redirect.yaml + :caption: public/fileadmin/forms/my_form_with_multiple_finishers.yaml + +.. _apireference-finisheroptions-redirectfinisher: + +Using a Redirect finisher in PHP code +===================================== + +Developers can use the finisher key `Redirect` to create redirect finishers in their own classes: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\RedirectFinisher`. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_example-redirect.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_example-redirect.yaml new file mode 100644 index 0000000..c47c2c1 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_example-redirect.yaml @@ -0,0 +1,17 @@ +identifier: contact +type: Form +prototypeName: standard +finishers: + - + identifier: EmailToSender + options: + subject: 'Your Message: {message}' + ## ... + - + identifier: DeleteUploads + - + # Attention! The Redirect finisher stops the execution of all finishers + identifier: Redirect + options: + pageUid: 1 + additionalParameters: 'param1=value1¶m2=value2' diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..8db0dad --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,14 @@ +createFinisher('Redirect', [ + 'pageUid' => 1, + 'additionalParameters' => 'param1=value1¶m2=value2', + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_form.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_form.yaml new file mode 100644 index 0000000..36f6056 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/RedirectFinisher/_codesnippets/_form.yaml @@ -0,0 +1,10 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: Redirect + options: + pageUid: 1 + additionalParameters: 'param1=value1¶m2=value2' diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/Index.rst b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/Index.rst new file mode 100644 index 0000000..d2093e1 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/Index.rst @@ -0,0 +1,245 @@ +.. include:: /Includes.rst.txt +.. _concepts-finishers-savetodatabasefinisher: + +======================= +SaveToDatabase finisher +======================= + +The "SaveToDatabase finisher" saves data from a submitted form into a +database table. + +.. contents:: Table of contents + +.. note:: + + This finisher cannot be used in the backend form editor. It can only be + used in a form definition YAML file or programmatically. + +.. include:: /Includes/_NoteFinisher.rst + +.. _apireference-finisheroptions-savetodatabasefinisher-options: + +SaveToDatabase finisher options +=============================== + +The finisher options can be set in the form definition YAML file or +programmatically: + +.. _apireference-finisheroptions-savetodatabasefinisher-options-table: + +.. confval:: table + :name: savetodatabasefinisher-table + :type: string + :required: true + + Insert or update values in this table. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-mode: + +.. confval:: mode + :name: savetodatabasefinisher-mode + :type: string + :default: `'insert'` + + `insert` + will create a new database row with the values from the submitted form + and/or some predefined values. See also :confval:`savetodatabasefinisher-elements` and + :confval:`savetodatabasefinisher-databaseColumnMappings`. + + `update` + will update a database row with the values from the submitted form + and/or some predefined values. In this case :confval:`savetodatabasefinisher-whereClause` is required. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-whereclause: + +.. confval:: whereClause + :name: savetodatabasefinisher-whereClause + :type: array + :required: true (if mode = update) + :default: `[]` + + The ``where`` clause for a database update action. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements: + +.. confval:: elements + :name: savetodatabasefinisher-elements + :type: array + :required: true + + Use `options.elements` to map form element values to database columns (they must exist). + Each key in `options.elements` has to match a form element identifier. + The value of each key in `options.elements` is an array containing additional information. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-mapondatabasecolumn: + +.. confval:: elements..mapOnDatabaseColumn + :name: savetodatabasefinisher-elements-mapOnDatabaseColumn + :type: string + :required: true + + The value from the submitted form element with the identifier + `` will be written into this database column. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-skipifvalueisempty: + +.. confval:: elements..skipIfValueIsEmpty + :name: savetodatabasefinisher-elements-skipIfValueIsEmpty + :type: bool + :default: `false` + + Set this to true if the database column should not be written if the value from the + submitted form element with the identifier `` is empty + (e.g. for password fields). Empty means strings without content, whitespace is valid content. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-hashed: + +.. confval:: elements..hashed + :name: savetodatabasefinisher-elements-hashed + :type: bool + :default: `false` + + Set this to true if the value from the submitted form element should be hashed before + writing into the database. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-savefileidentifierinsteadofuid: + +.. confval:: elements..saveFileIdentifierInsteadOfUid + :name: savetodatabasefinisher-elements-saveFileIdentifierInsteadOfUid + :type: bool + :default: `false` + + By default, the uid of the FAL object will be written into the database column. + Set this to true if you want to store the FAL identifier + (e.g. `1:/user_uploads/some_uploaded_pic.jpg`) instead. + + This only applies for form elements which create a FAL object like + `FileUpload` or `ImageUpload`. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-elements-dateformat: + +.. confval:: elements..dateFormat + :name: savetodatabasefinisher-elements-dateFormat + :type: string + :default: `'U'` + + If the internal datatype is :php:`\DateTime` (true for the form element type + :yaml:`Date`), the object needs to be converted into a string. + This option defines the format of the date. You can use any format accepted by + the PHP :php:`date()` function. + Default is `'U'` (Unix timestamp). + +.. _apireference-finisheroptions-savetodatabasefinisher-options-databasecolumnmappings: + +.. confval:: databaseColumnMappings + :name: savetodatabasefinisher-databaseColumnMappings + :type: array + :default: `[]` + + Use this to map database columns to values. + Each key within `options.databaseColumnMappings` has to match an existing database column. + Each value in `options.databaseColumnMappings` is an array with + additional information. + + This mapping is done *before* :confval:`savetodatabasefinisher-elements` are mapped. + If you map both, the value from :confval:`savetodatabasefinisher-elements` will override the + :confval:`savetodatabasefinisher-databaseColumnMappings-value`. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-databasecolumnmappings-value: + +.. confval:: databaseColumnMappings..value + :name: savetodatabasefinisher-databaseColumnMappings-value + :type: string + :required: true + + The value which will be written to the database column. + You can also use the :ref:`FormRuntime accessor feature + ` + to access properties from the `FormRuntime`, e.g. `{}`. + +.. _apireference-finisheroptions-savetodatabasefinisher-options-databasecolumnmappings-skipifvalueisempty: + +.. confval:: databaseColumnMappings..skipIfValueIsEmpty + :name: savetodatabasefinisher-databaseColumnMappings-skipIfValueIsEmpty + :type: bool + :default: `false` + + Set this to true if the database column should not be written if the value from + :confval:`savetodatabasefinisher-databaseColumnMappings-value` is empty. + +.. confval:: translation.propertiesExcludedFromTranslation + :name: savetodatabasefinisher-translation-propertiesExcludedFromTranslation + :type: array + :default: `[]` + + Defines a list of finisher option properties to be excluded from + translation. + + If set, these properties are not processed by the + :php-short:`\TYPO3\CMS\Form\Service\TranslationService` during translation. + This prevents the values from being replaced by + translated equivalents, even if translations exist for those options. + + This option is usually generated when FlexForm overrides + exist and normally does not need to be set manually in the form + definition. + + See `Skip translation of overridden form finisher options `_ + for an example. + +.. _concepts-finishers-savetodatabasefinisher-yaml: + +SaveToDatabase finisher in a YAML form definition +================================================= + +This finisher saves data from a submitted form into a database table. + +.. literalinclude:: _codesnippets/_form.yaml + :linenos: + :caption: public/fileadmin/forms/my_form.yaml + +.. _concepts-finishers-savetodatabasefinisher-example-news: + +Example: adding uploads to ext:news (fal_related_files and fal_media): +====================================================================== + +.. literalinclude:: _codesnippets/_example-fal-uploads_news.yaml + :linenos: + :caption: public/fileadmin/forms/my_form_with_multiple_finishers.yaml + +.. _apireference-finisheroptions-savetodatabasefinisher: + +Using a SaveToDatabase finisher in PHP code +================================================ + +Developers can use the finisher key `SaveToDatabase` to create +flash message finishers in their own classes: + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + :linenos: + +This finisher is implemented in :php:`TYPO3\CMS\Form\Domain\Finishers\SaveToDatabaseFinisher`. + +.. _concepts-finishers-savetodatabasefinisher-multiple: + +Multiple database operations +============================ + +You can use options to perform multiple database operations. + +Example form definition file (performs inserts): + +.. literalinclude:: _codesnippets/_example-fal-uploads_news.yaml + :linenos: + :caption: public/fileadmin/forms/my_form_with_multiple_finishers.yaml + +Using PHP code (performs an update): + +.. literalinclude:: _codesnippets/_finisher.php.inc + :language: php + :linenos: + +You can access inserted UIDs with '{SaveToDatabase.insertedUids.}'. +If you perform an insert operation, the inserted values will be stored in the FinisherVariableProvider. + references the numeric options.* key. diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_example-fal-uploads_news.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_example-fal-uploads_news.yaml new file mode 100644 index 0000000..3e2d6a2 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_example-fal-uploads_news.yaml @@ -0,0 +1,73 @@ +- + identifier: SaveToDatabase + options: + - + table: tx_news_domain_model_news + mode: insert + elements: + my-field: + mapOnDatabaseColumn: bodytext + imageupload-1: + mapOnDatabaseColumn: fal_media + fileupload-1: + mapOnDatabaseColumn: fal_related_files + databaseColumnMappings: + pid: + value: 3 + tstamp: + value: '{__currentTimestamp}' + datetime: + value: '{__currentTimestamp}' + crdate: + value: '{__currentTimestamp}' + hidden: + value: 1 + - + table: sys_file_reference + mode: insert + elements: + imageupload-1: + mapOnDatabaseColumn: uid_local + skipIfValueIsEmpty: true + databaseColumnMappings: + tablenames: + value: tx_news_domain_model_news + fieldname: + value: fal_media + tstamp: + value: '{__currentTimestamp}' + crdate: + value: '{__currentTimestamp}' + showinpreview: + value: 1 + uid_foreign: + value: '{SaveToDatabase.insertedUids.0}' + - + table: sys_file_reference + mode: insert + elements: + fileupload-1: + mapOnDatabaseColumn: uid_local + skipIfValueIsEmpty: true + databaseColumnMappings: + tablenames: + value: tx_news_domain_model_news + fieldname: + value: fal_related_files + tstamp: + value: '{__currentTimestamp}' + crdate: + value: '{__currentTimestamp}' + uid_foreign: + value: '{SaveToDatabase.insertedUids.0}' + - + table: sys_file_reference + mode: update + whereClause: + uid_foreign: '{SaveToDatabase.insertedUids.0}' + uid_local: 0 + databaseColumnMappings: + pid: + value: 0 + uid_foreign: + value: 0 diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher-multiple.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher-multiple.php.inc new file mode 100644 index 0000000..bc04812 --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher-multiple.php.inc @@ -0,0 +1,30 @@ +createFinisher('SaveToDatabase', [ + 1 => [ + 'table' => 'my_table', + 'mode' => 'insert', + 'databaseColumnMappings' => [ + 'some_column' => ['value' => 'cool'], + ], + ], + 2 => [ + 'table' => 'my_other_table', + 'mode' => 'update', + 'whereClause' => [ + 'pid' => 1, + ], + 'databaseColumnMappings' => [ + 'some_other_column' => ['value' => '{SaveToDatabase.insertedUids.1}'], + ], + ], + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher.php.inc b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher.php.inc new file mode 100644 index 0000000..cbff43e --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_finisher.php.inc @@ -0,0 +1,31 @@ +createFinisher('SaveToDatabase', [ + 'table' => 'fe_users', + 'mode' => 'update', + 'whereClause' => [ + 'uid' => 1, + ], + 'databaseColumnMappings' => [ + 'pid' => ['value' => 1], + ], + 'elements' => [ + 'textfield-identifier-1' => ['mapOnDatabaseColumn' => 'first_name'], + 'textfield-identifier-2' => ['mapOnDatabaseColumn' => 'last_name'], + 'textfield-identifier-3' => ['mapOnDatabaseColumn' => 'username'], + 'advancedpassword-1' => [ + 'mapOnDatabaseColumn' => 'password', + 'skipIfValueIsEmpty' => true, + 'hashed' => true + ], + ], + ]); + } +} diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form-multiple.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form-multiple.yaml new file mode 100644 index 0000000..62597fe --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form-multiple.yaml @@ -0,0 +1,22 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: SaveToDatabase + options: + 1: + table: 'my_table' + mode: insert + databaseColumnMappings: + some_column: + value: 'cool' + 2: + table: 'my_other_table' + mode: update + whereClause: + pid: 1 + databaseColumnMappings: + some_other_column: + value: '{SaveToDatabase.insertedUids.1}' diff --git a/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form.yaml b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form.yaml new file mode 100644 index 0000000..b7bc3ec --- /dev/null +++ b/Documentation/I/Concepts/Finishers/ReadyToUseFinishers/SaveToDatabaseFinisher/_codesnippets/_form.yaml @@ -0,0 +1,28 @@ +identifier: example-form +label: 'example' +type: Form + +finishers: + - + identifier: SaveToDatabase + options: + table: 'fe_users' + mode: update + whereClause: + uid: 1 + databaseColumnMappings: + tstamp: + value: '{__currentTimestamp}' + pid: + value: 1 + elements: + textfield-identifier-1: + mapOnDatabaseColumn: 'first_name' + textfield-identifier-2: + mapOnDatabaseColumn: 'last_name' + textfield-identifier-3: + mapOnDatabaseColumn: 'username' + advancedpassword-1: + mapOnDatabaseColumn: 'password' + skipIfValueIsEmpty: true + hashed: true diff --git a/Documentation/I/Concepts/FormConfigurationFormDefinition/Index.rst b/Documentation/I/Concepts/FormConfigurationFormDefinition/Index.rst new file mode 100644 index 0000000..3eb7ba6 --- /dev/null +++ b/Documentation/I/Concepts/FormConfigurationFormDefinition/Index.rst @@ -0,0 +1,113 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-formdefinition-vs-formconfiguration: + +Form configuration vs. form definition +====================================== + +Up to this point, we have mainly looked at form framework configuration. +In short, **form configuration** is based on *prototypes* and allows you to define: + +- which form elements, finishers, and validators are available to the system, +- how they are pre-configured, +- how they are displayed in the frontend and backend. + +However, a second important part of the form framework is **form definition**, +which is configuration but for *specific* forms, for example the ones users define. Form +definition includes: + +- form elements and their validators, +- the order of the form elements on the form +- the finishers that are fired when the form is submitted +- values of form element properties. + + +In other words, a ``Text`` form element would be defined in **form configuration** +but a ``Text`` form element located on page 1 at position 1 of a specific form +would be defined in a **form definition**. A **form definition** might also define +a placeholder (HTML attribute) with a value of "Your name +here" in a form element. Form definitions are created by the backend ``form editor``. + +Example form definition (for a specific form) +--------------------------------------------- + +.. code-block:: yaml + + identifier: ext-form-simple-contact-form-example + label: 'Simple Contact Form' + prototype: standard + type: Form + + finishers: + - + identifier: EmailToReceiver + options: + subject: 'Your message' + recipients: + your.company@example.com: 'Your Company name' + ceo@example.com: 'CEO' + senderAddress: '{email}' + senderName: '{name}' + + renderables: + - + identifier: page-1 + label: 'Contact Form' + type: Page + + renderables: + - + identifier: name + label: 'Name' + type: Text + properties: + fluidAdditionalAttributes: + placeholder: 'Name' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: subject + label: 'Subject' + type: Text + properties: + fluidAdditionalAttributes: + placeholder: 'Subject' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: email + label: 'Email' + type: Text + properties: + fluidAdditionalAttributes: + placeholder: 'Email address' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: EmailAddress + - + identifier: message + label: 'Message' + type: Textarea + properties: + fluidAdditionalAttributes: + placeholder: '' + defaultValue: '' + validators: + - + identifier: NotEmpty + - + identifier: hidden + label: 'Hidden Field' + type: Hidden + - + identifier: summarypage + label: 'Summary page' + type: SummaryPage diff --git a/Documentation/I/Concepts/FormEditor/Index.rst b/Documentation/I/Concepts/FormEditor/Index.rst new file mode 100644 index 0000000..199071c --- /dev/null +++ b/Documentation/I/Concepts/FormEditor/Index.rst @@ -0,0 +1,579 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-formeditor: + +Form editor +=========== + + +.. _concepts-formeditor-general: + +What does it do? +---------------- + +The ``form editor`` is a powerful graphical user interface in the TYPO3 backend +which allows editors to create ``form definitions`` without writing a single line +of code. These ``form definitions`` are used by the frontend process to +render beautiful forms. + +The ``form editor`` is a modular interface which consists of the following +components: + +- Stage: main visual component of the backend ``form editor`` where displaying + form elements in an abstract view or a frontend preview (in the middle of the ``form editor``) +- Tree: displays the structure of the form as a tree (on the left) +- Inspector: context specific toolbar which displays + form element options and where options can be edited (on the right) +- Core: core functionality of the ``form editor`` +- ViewModel: defines and controls the visual display +- Mediator: delegates component events +- Modals: processes modals +- FormEditor: provides API functions +- Helper: helper functions for the manipulation of DOM elements + +The ``Modals``, ``Inspector``, and ``Stage`` components +can be modified by configuration. The ``Inspector`` component +is modular and extremely flexible. Integrators can add +``inspector editors`` (input fields of different types) +to allow backend editors to alter form element +options. + +The diagram below shows Javascript module interaction between the form editor and the +core, viewmodel and mediator. + +.. figure:: ../../Images/javascript_module_interaction.png + :alt: JavaScript module interaction + + JavaScript module interaction + +The ``form editor`` configuration is under the following configuration path: + +.. code-block:: yaml + + prototypes: + standard: + formEditor: + +Here you can configure different aspects of the ``form editor`` under the following +configuration paths: + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + : + formEditor: + finishersDefinition: + + formEditor: + validatorsDefinition: + + formEditor: + + +.. _concepts-formeditor-components-in-detail: + +Form editor components in detail +-------------------------------- + + +.. _concepts-formeditor-stage: + +Stage +^^^^^ + +The ``Stage`` is the central visual component of the form editor and it +can display form elements in two different modes: + +- abstract view: all the form elements on a ``Page`` (a step) presented in an + abstract way, +- frontend preview: renders the form as it will be displayed in + the frontend (to render the form exactly the same as in the frontend, make sure + your frontend CSS is loaded in the backend) + +By default, the frontend templates of :t3ext:`form` are based on `Bootstrap`_. +Since the backend of TYPO3 CMS also depends on `Bootstrap`_, +the corresponding CSS files will already loaded in the backend. +Nevertheless, some CSS is overridden and extended in order +to meet the specific needs of the TYPO3 backend, meaning frontend preview +(in the backend) could differ compared to the "real" frontend. + +If your frontend preview requires additional CSS or a CSS framework +then go ahead and configure a specific ``prototype`` accordingly. + +Beside the frontend templates, there are also templates for the abstract +view, i.e. you can customize the rendering of the abstract view for each +form element. If you have created your own form elements, in most cases you +will fall back to the already existing Fluid templates. But remember, you +are always able to create your own Fluid templates and adapt the abstract view +to suit your needs. + +For more information, read the following chapter: ':ref:`Common abstract view form element templates`'. + +.. _Bootstrap: https://getbootstrap.com/ + + +.. _concepts-formeditor-inspector: + +Inspector +^^^^^^^^^ + +The ``Inspector`` is on the right side of the ``form editor``. It is a modular, +flexible, and context-specific toolbar +and depends on which form element is currently selected. The ``Inspector`` +is where you can edit form element options using ``inspector editors``. +The interface is easily customized by YAML configuration. You can define form element +properties and how they can be edited. + +You can edit form element properties (like ``properties.placeholder``) +as well as ``property collections``. They are defined at the form element level +in the YAML configuration file. There are two types of ``property collections``: + +- validators +- finishers + +``Property collections`` are also configured by ``inspector editors`` and this +allows you to do some cool stuff. Imagine that you have a "Number range" validator with +two validator options "Minimum" and "Maximum" and two form elements, "Age +spouse" and "Age infant". You could set the validator for both form elements, +but make "Minimum" non-editable and pre-fill "Maximum" with a value for the "Age +infant" form element only and not the "Age spouse" form element. + +.. _concepts-formeditor-translation-formeditor: + +Translation of the form editor +------------------------------ + +All option values below the following configuration keys can be translated: + +.. code-block:: yaml + + prototypes: + standard: + formEditor: + formElementsDefinition: + : + formEditor: + finishersDefinition: + + formEditor: + validatorsDefinition: + + formEditor: + +The ``form editor`` translation files are loaded as follows: + +.. code-block:: yaml + + prototypes: + standard: + formEditor: + translationFiles: + # custom translation file + 20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf' + +Option values are searched for in the defined +translation files. If a translation is found, the translated option value +will be used. + +As an example, if the following option is defined: + +.. code-block:: yaml + + ... + label: 'formEditor.elements.Form.editor.finishers.label' + ... + +The translation key ``formEditor.elements.Form.editor.finishers.label`` +is first searched for in the file +``20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf'`` +and then in the file ``10: 'EXT:form/Resources/Private/Language/Database.xlf'`` +(loaded by default by EXT:form). If nothing is found, the option value will be +displayed unmodified. + + +.. _concepts-formeditor-customization-formeditor: + +Customization of the form editor +-------------------------------- + +The form editor can be customized by YAML +configuration in the configuration. The configuration is not stored in one central configuration +file. Instead, configuration is defined for each form element (see +`EXT:form/form/Configuration/Yaml/FormElements/`). In addition, +the :yaml:`Form` element itself (see `EXT:form/Configuration/Yaml/FormElements/Form.yaml`) +has some basic configuration. + +A common customization is to remove form elements from the form +editor. Unlike other TYPO3 modules, the form editor cannot be configured +using backend user groups and `Access Lists` - it can only be done by YAML configuration. + +Quite often, integrators tend to unset form elements as shown below. +In this example, the :yaml:`AdvancedPassword` form element is completely removed from +the form framework. Integrators and developers will no longer be able to use +the :yaml:`AdvancedPassword` element in their YAML form definitions or via API. + +.. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + prototypes: + standard: + formElementsDefinition: + AdvancedPassword: null + + +The correct way is to unset the :ref:`group property `. +This property defines which group in the ``form editor`` "new Element" +modal the form element should belong in. Unsetting this property will remove the +form element safely from the form editor: + +.. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + prototypes: + standard: + formElementsDefinition: + AdvancedPassword: + formEditor: + group: null + + +.. _concepts-formeditor-extending: + +Extending the form editor +------------------------- + +Learn :ref:`here ` +how to make finishers configurable in the backend form editor. + + +.. _concepts-formeditor-basicjavascriptconcepts: + +Basic JavaScript concepts +------------------------- + +The form framework was designed to be as extendable as possible. Sooner or +later, you will want to customize ``form editor`` components using +JavaScript. This is especially true if you want to create your own +``inspector editors``. In order to achieve this, you can implement your own +JavaScript modules. Those modules will include the required algorithms for +the ``inspector editors`` and the ``abstract view`` as well as your own +events. + + +.. _concepts-formeditor-basicjavascriptconcepts-registercustomjavascriptmodules: + +Register custom JavaScript modules +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can use the following configuration YAML to register your JavaScript module. + +.. code-block:: yaml + + prototypes: + standard: + formEditor: + dynamicJavaScriptModules: + additionalViewModelModules: + 10: '@my-vendor/my-site-package/backend/form-editor/view-model.js' + +.. code-block:: php + + # Configuration/JavaScriptModules.php + ['form'], + 'imports' => [ + '@myvendor/my-site-package/' => 'EXT:my_site_package/Resources/Public/JavaScript/', + ], + ]; + +In the configuration above, the JavaScript files have to be in the folder +``my_site_package/Resources/Public/JavaScript/backend/form-editor/view-model.js``. + +The following example module is a template you can use containing the recommended setup. + +.. code-block:: javascript + + /** + * Module: @my-vendor/my-site-package/backend/form-editor/view-model.js + */ + import * as Helper from '@typo3/form/backend/form-editor/helper.js' + + /** + * @private + * + * @var object + */ + let _formEditorApp = null; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param object + * @return object + */ + function getHelper() { + return Helper; + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return void + * @throws 1491643380 + */ + function _helperSetup() { + assert('function' === typeof Helper.bootstrap, + 'The view model helper does not implement the method "bootstrap"', + 1491643380 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + */ + function _subscribeEvents() { + getPublisherSubscriber().subscribe('some/eventName/you/want/to/handle', function(topic, args) { + myCustomCode(); + }); + }; + + /** + * @private + * + * @return void + */ + function myCustomCode() { + }; + + /** + * @public + * + * @param object formEditorApp + * @return void + */ + export function bootstrap(formEditorApp) { + _formEditorApp = formEditorApp; + _helperSetup(); + _subscribeEvents(); + }; + + +.. _concepts-formeditor-basicjavascriptconcepts-events: + +Events +^^^^^^ + +Event handling in :t3ext:`form` is based on the ``Publish/Subscribe Pattern``. +To learn more about this terrific pattern, see: https://addyosmani.com/resources/essentialjsdesignpatterns/book/. +Please note that the processing sequence of the subscribers cannot be +influenced. Furthermore, there is no information flow between the +subscribers. All events are asynchronous. + +For more information, head to the API reference and read the section about +':ref:`Events`'. + + +.. _concepts-formeditor-basicjavascriptconcepts-formelementmodel: + +FormElement model +^^^^^^^^^^^^^^^^^ + +In the JavaScript code, each form element is represented by a +``FormElement model``. This model can be seen as a copy of the ``form definition`` +enriched with some additional data. The following example shows +you a ``form definition`` and, below it, the debug output of ``FormElement model``. + +.. code-block:: yaml + + identifier: javascript-form-element-model + label: 'JavaScript FormElement model' + type: Form + finishers: + - + identifier: EmailToReceiver + options: + subject: 'Your message: {subject}' + recipients: + your.company@example.com: 'Your Company name' + ceo@example.com: 'CEO' + senderAddress: '{email}' + senderName: '{name}' + replyToRecipients: + replyTo.company@example.com: 'Your Company name' + carbonCopyRecipients: + cc.company@example.com: 'Your Company name' + blindCarbonCopyRecipients: + bcc.company@example.com: 'Your Company name' + addHtmlPart: true + attachUploads: 'true' + translation: + language: '' + title: '' + renderables: + - + identifier: page-1 + label: 'Contact Form' + type: Page + renderables: + - + identifier: name + label: Name + type: Text + properties: + fluidAdditionalAttributes: + placeholder: Name + defaultValue: '' + validators: + - + identifier: NotEmpty + +.. code-block:: javascript + + { + "identifier": "javascript-form-element-model", + "label": "JavaScript FormElement model", + "type": "Form", + "prototypeName": "standard", + "__parentRenderable": null, + "__identifierPath": "example-form", + "finishers": [ + { + "identifier": "EmailToReceiver", + "options": { + "subject": "Your message: {subject}", + "recipients": { + "your.company@example.com": "Your Company name", + "ceo@example.com": "CEO" + }, + "senderAddress": "{email}", + "senderName": "{name}", + "replyToRecipients": { + "replyTo.company@example.com": "Your Company name" + }, + "carbonCopyRecipients": { + "cc.company@example.com": "Your Company name" + }, + "blindCarbonCopyRecipients": { + "bcc.company@example.com": "Your Company name" + }, + "addHtmlPart": true, + "attachUploads": true, + "translation": { + "language": "" + }, + "title": "" + } + } + ], + "renderables": [ + { + "identifier": "page-1", + "label": "Contact Form", + "type": "Page", + "__parentRenderable": "example-form (filtered)", + "__identifierPath": "example-form/page-1", + "renderables": [ + { + "identifier": "name", + "defaultValue": "", + "label": "Name", + "type": "Text", + "properties": { + "fluidAdditionalAttributes": { + "placeholder": "Name" + } + }, + "__parentRenderable": "example-form/page-1 (filtered)", + "__identifierPath": "example-form/page-1/name", + "validators": [ + { + "identifier": "NotEmpty" + } + ] + } + ] + } + ] + } + +For each form element which has child elements, there is a property +called ``renderables``. ``renderables`` are arrays of ``FormElement models`` +of child elements. + +The ``FormElement model`` is therefore a combination of the +of ``form definition`` data and some additional information: + +- __parentRenderable +- __identifierPath + +The following methods can be used to access ``FormElement model`` data: + +- get() +- set() +- unset() +- on() +- off() +- getObjectData() +- toString() +- clone() + +Head to the API reference to read more about +the :ref:`FormElement model`. diff --git a/Documentation/I/Concepts/FormFileStorages/Index.rst b/Documentation/I/Concepts/FormFileStorages/Index.rst new file mode 100644 index 0000000..08bf8d6 --- /dev/null +++ b/Documentation/I/Concepts/FormFileStorages/Index.rst @@ -0,0 +1,78 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-form-file-storages: + +Form/ File storage +================== + +Form definitions can also be stored in and shipped with your own +extensions and backend users can then +embed your forms. Furthermore, you can configure that your form +definitions: + +- can be edited in the ``form editor``, +- can be deleted with the ``form manager``. + +By default, all these options are turned off because dynamic content inside an +extension - possibly version-controlled - is not a good idea. There is also no +ACL system available. + +**File uploads** are saved in file mounts. They are handled +as FAL objects. The file mounts for file uploads can be configured. +When adding/ editing a file upload element, backend users can select the +storage for the uploads. + +Add your extension path as an additional file mount for form definitions as follows: + +.. code-block:: yaml + + persistenceManager: + allowedExtensionPaths: + 10: EXT:my_site_package/Resources/Private/Forms/ + +Allow backend users to **edit** forms stored in your extension as follows: + +.. code-block:: yaml + + persistenceManager: + allowSaveToExtensionPaths: true + +Allow backend users to **delete** forms stored in your extension as follows: + +.. code-block:: yaml + + persistenceManager: + allowDeleteFromExtensionPaths: true + +The following YAML shows the default file mount setup for file (and image) uploads. + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + FileUpload: + formEditor: + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + editors: + 400: + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + properties: + saveToFileMount: '1:/user_upload/' + ImageUpload: + formEditor: + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + editors: + 400: + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' diff --git a/Documentation/I/Concepts/FormManager/Index.rst b/Documentation/I/Concepts/FormManager/Index.rst new file mode 100644 index 0000000..d1144ea --- /dev/null +++ b/Documentation/I/Concepts/FormManager/Index.rst @@ -0,0 +1,133 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-formmanager: + +Form manager +============ + + +.. _concepts-formmanager-general: + +What does it do? +---------------- + +You will find the ``form manager`` in the backend :guilabel:`Web > Forms` backend +module. Editors can use the ``form manager`` to administer forms stored on file +mounts that they have access to. The ``form manager``: + +- lists all forms +- allows users to create, edit, duplicate, and delete forms +- identifies the storage folder +- gives an overview of which pages the forms are on. + +Creation and duplication of forms is made easier by a ``form wizard``. +The wizard guides the editor through form creation and offers a +variety of settings, such as the file +mount, the prototype, and start templates. + +.. figure:: ../../Images/form_manager.png + :alt: The form manager + + TYPO3 Backend with opened module 'Forms' displaying the form manager. + + +.. _concepts-formmanager-starttemplate: + +Start templates +--------------- + +Editors can select a ``Start template`` when they are creating a new form. A +``Start template`` is a ``form definition`` which hasn't been assigned a +``prototypeName`` (the ``prototypeName`` property is normally used as the +foundation of a new form). + +An integrator can create as many ``Start templates`` as they wish for a particular +``prototype``. After the ``Start templates`` have been defined the integrator can then: + +- open :guilabel:`Web > Forms` +- create a new form by clicking on the appropriate button +- enter the 'Form name' and click the 'Advanced settings' checkbox +- select a ``Start template`` during the next steps + +Integrators have to define ``Start templates`` so that they can be selected +by editors. Also, the same ``Start template`` +can be used for several ``prototypes``. To do this, make sure the +``start template`` form elements are defined in the corresponding ``prototypes``. + +For example, imagine an integrator has :ref:`configured` +a prototype called 'routing' which contains a form element of type +```` 'locationPicker'. The element is only +defined in this prototype. The integrator has created a ``Start template`` +which contains the 'locationPicker' form element. A backend editor could now +select and use this ``Start template`` with the 'locationPicker' form element, +as long as the ``prototype`` is 'routing'. If the integrator +adds this form element to another ``prototype``, the process would +crash. The 'locationPicker' form element is only known to the 'routing' +``prototype``. + +The following example shows a ``Start template``. A +``Start template`` requires at least the root form element +('Form') and a 'Page'. + + +.. code-block:: yaml + + type: 'Form' + identifier: 'blankForm' + label: '[Blank Form]' + renderables: + - + type: 'Page' + identifier: 'page-1' + label: 'Page' + +The ``form manager`` form wizard displays +a list of all :ref:`pre-configured` +``Start templates``.When a backend editor creates a form using a +``Start template``, a new ``form definition`` is generated based on that +``Start template``. The ``form definition`` ``propertyName`` will be that of the +chosen ``prototype``.The ``identifier`` of the root form element ('Form') is set +to the entered "Form name". This name is also used for the +property `` label`` of the 'Form' element. Finally, the ``form editor`` is +loaded and displays the newly created form. + + +.. _concepts-formmanager-translation-starttemplate: + +Translation of the form manager +------------------------------- + +All option values below the ``form editor`` key in the form configuration can be +translated: + +.. code-block:: yaml + + formManager: + +The ``form manager`` translation files are loaded as follows: + +.. code-block:: yaml + + formManager: + translationFiles: + # custom translation file + 20: 'EXT:my_site_package/Resources/Private/Language/Form/Database.xlf' + +The process searches for each option value within all of the defined +translation files. If a translation is found, the translated option value +will be used in preference. + +For the following option value: + +.. code-block:: yaml + + ... + label: 'formManager.selectablePrototypesConfiguration.standard.label' + ... + +the process searches for the translation key ``formManager.selectablePrototypesConfiguration.standard.label`` +in the file under key 20 ``20: 'EXT:my_site_package/Resources/Private/Language/Form/Database.xlf'`` +and then the file in EXT:form ``10: 'EXT:form/Resources/Private/Language/Database.xlf'`` +(loaded by default). If nothing is found, the option value will be +displayed unmodified. diff --git a/Documentation/I/Concepts/FormPlugin/Index.rst b/Documentation/I/Concepts/FormPlugin/Index.rst new file mode 100644 index 0000000..b5b6e2c --- /dev/null +++ b/Documentation/I/Concepts/FormPlugin/Index.rst @@ -0,0 +1,100 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-formplugin: + +Form plugin +=========== + + +.. _concepts-formplugin-general: + +What does it do? +---------------- + +The ``form plugin`` allows you to assign a form to a page and view it in the +frontend. The form can have been created via the ``form editor`` or shipped with +your extension. Forms can be re-used throughout the TYPO3 installation and backend editors +can override form definitions. At the moment, only finisher options can be overridden but the +possibilities depend on the configuration of the underlying prototype. + +Imagine that your form contains a redirect finisher. The redirect target is set +globally and valid for the whole ``form definition``. When they are adding the form +to a page, a backend editor can define a redirect target that is different to the +'global' form definition. This setting is only valid on the page containing the plugin. + +Read more about changing :ref:`general` +and :ref:`specific form plugin configuration`. + + +.. _concepts-formplugin-exclude-override: + +Exclude options from overrides +------------------------------ + +Sometimes it is useful to prevent options from being overridden by the +form plugin. You can do this by unsetting the options in your +general forms configuration YAML. To unset options use the YAML NULL (:yaml:`~`) value. + +In this example, four ``EmailToReceiver`` finisher fields are unset. The +options will be removed from the form plugin but not the form editor. + +.. code-block:: yaml + + prototypes: + standard: + finishersDefinition: + EmailToReceiver: + FormEngine: + elements: + senderAddress: ~ + senderName: ~ + replyToRecipients: ~ + translation: ~ + + +.. _concepts-formplugin-translation-formengine: + +Translation of form plugin +-------------------------- + +All option values under the following configuration keys can be +translated: + +.. code-block:: yaml + + prototypes: + standard: + finishersDefinition: + + formEngine: + +``Form plugin`` translation files are loaded as follows: + +.. code-block:: yaml + + prototypes: + standard: + formEngine: + translationFiles: + # custom translation file + 20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf' + +Each option value is searched for in the defined +translation files. If a translation is found, the translated option value +will be used. + +Imagine that the following option value is defined: + +.. code-block:: yaml + + ... + label: 'tt_content.finishersDefinition.EmailToReceiver.label' + ... + +The translation key +``tt_content.finishersDefinition.EmailToReceiver.label`` is first searched for in the file +``20: 'EXT:my_site_package/Resources/Private/Language/Database.xlf'`` and +then in the file 10: 'EXT:form/Resources/Private/Language/Database.xlf' +(loaded by EXT:form by default). If nothing is found, the option value will be +displayed unmodified. diff --git a/Documentation/I/Concepts/FrontendRendering/Index.rst b/Documentation/I/Concepts/FrontendRendering/Index.rst new file mode 100644 index 0000000..ac7f804 --- /dev/null +++ b/Documentation/I/Concepts/FrontendRendering/Index.rst @@ -0,0 +1,937 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-frontendrendering: + +================== +Frontend rendering +================== + +.. _concepts-frontendrendering-templates: + +Templates +========= + +Fluid templates in the form framework are based on `Bootstrap`_. + +.. _Bootstrap: https://getbootstrap.com/ + +.. _concepts-frontendrendering-templates-customtemplates: + +Custom templates +---------------- + +In order to use your own Fluid templates for frontend forms, +register your own template paths via YAML in the form configuration +(here under the default ``standard`` prototype). + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + templateRootPaths: + 100: 'EXT:my_site_package/Resources/Private/Frontend/Templates/' + partialRootPaths: + 100: 'EXT:my_site_package/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 100: 'EXT:my_site_package/Resources/Private/Frontend/Layouts/' + +If your `form definition` then references the `standard` prototype, the form +framework will look for Fluid templates in +:directory:`EXT:my_site_package/Resources/Private/Frontend/[*]`. + +The `Form` element is the 'main' element. The framework will look for +:file:`Form.html` in :directory:`templateRootPaths`. For all other elements, +it will look in :directory:`partialRootPaths`. A partial has the same name +as the `formElementTypeIdentifier` property, for example, +a `Text` template will be in a partial named :file:`Text.html` in +:directory:`partialRootPaths`. + + +.. _concepts-frontendrendering-templates-singlevalues: + +Form element values in finisher templates +----------------------------------------- + +Use the :php:`RenderFormValueViewHelper` to access form element values in your +finisher templates. This ViewHelper accepts a single form +element and renders it. The following example shows the :php:`RenderFormValueViewHelper` +being called with two parameters (`renderable` and `as`) to output the value of a +`message` field. The value :fluid:`{formValue.processedValue}` can then +be manipulated with Fluid, styled, etc. + +.. code-block:: html + + + {formValue.processedValue} + + +Names of your form elements can be found in your form definition (in your +individual YAML files or in the :guilabel:`System > Configuration` module if you +have the lowlevel extension installed). Or use the debug ViewHelper in Fluid to +list all the form elements. + +.. code-block:: html + + {page.rootForm.elements} + + +.. _concepts-frontendrendering-translation: + +Translation +=========== + +.. _concepts-frontendrendering-translation-formdefinition: + +Translate form definition +------------------------- + +Translation of `form definitions` works differently to the usual translation +of the backend. Currently, there is no graphical user interface +for this translation process. + +If `form definition` properties were translated in the same way as the rest of the backend, +a backend editor using the `form editor` to edit a form they would see long +unwieldy translation keys. In order to avoid this, form element *properties* are translated +instead of their values. The form framework does not look for translation keys +in a translation file. Instead, the system searches for translations +of the form element properties independent of their property values. The +property values are ignored if an entry is found in a +translation file. The form element property values are overridden by the +translated values. + +This approach is a compromise between two scenarios: creating forms using the `form editor` +or creating `form definitions` (which could later be edited in the +`form editor`). An editor can create forms just using the `form editor` where +form element property values are displayed in the default language. An integrator +can provide additional language files which translate the form depending on the +prototype. + +Add additional translation files to the form configuration as follows: + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + translation: + translationFiles: + # custom translation file + 20: 'EXT:my_site_package/Resources/Private/Language/Form/locallang.xlf' + +The translationFiles array is processed from the highest key to the lowest, i.e. your +translation file with key `20` is processed before translation files with key +'10' in EXT:form. If no key is found in the translation files, a +property value will be displayed unmodified. + +The following properties can be translated: + +* label +* defaultValue (scalar values only; array values, e.g. for :yaml:`MultiCheckbox`, are not translated) +* properties.[*] +* properties.options.[*] +* properties.fluidAdditionalAttributes.[*] +* renderingOptions.[*] + +The translation keys are put together based on a specific pattern and there is a +order (fallback chain) for the translations that depends on translation scenarios. +These are the translation scenarios: + +* translation of a form element property for a specific form (`formDefinitionIdentifier) and form + element (`ElementIdentifier`) +* translation of a form element property for a specific form element (`formElementIdentifier`) and + various forms +* translation of a form element property for an element type (`elementType`) and various + forms, e.g. the `Page` element + +The look-up process searches for translation keys in all given translation +files based on the following order (the same order as the translation scenarios above): + +* `.element..properties.` +* `element..properties.` +* `element..properties.` + +Translation of options (`properties.options`) in form elements, like the +`Select` element, have the following look-up order: + +* `.element..properties.options.` +* `element..properties.options.` + +.. _concepts-frontendrendering-translation-formdefinition-example: + +Example Form Definition +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: yaml + + identifier: ApplicationForm + type: Form + prototypeName: standard + label: 'Application form' + + renderables: + - + identifier: GeneralInformation + type: Page + label: 'General information' + + renderables: + - + identifier: LastName + type: Text + label: 'Last name' + properties: + placeholder: 'Please enter your last name.' + defaultValue: '' + - + identifier: Software + type: MultiSelect + label: 'Known software' + properties: + options: + value1: TYPO3 + value2: Neos + +In order to translate the form element `LastName`, the process will look for the following +translation keys in the translation files: + +* `ApplicationForm.element.LastName.properties.label` + (*.element..properties.*) +* `element.LastName.properties.label` + (*element..properties.*) +* `element.Text.properties.label` + (*element..properties.*) + +If none of these keys exist, 'Last name' will be displayed. + +The :yaml:`defaultValue` of `LastName` can be translated with the same fallback chain, +using ``properties.defaultValue`` as the property name: + +* `ApplicationForm.element.LastName.properties.defaultValue` +* `element.LastName.properties.defaultValue` +* `element.Text.properties.defaultValue` + +In order to translate the form element `Software`, the process will look for the following +translation keys in the translation files: + +* `ApplicationForm.element.Software.properties.label` + (*.element..properties.*) +* `element.Software.properties.label` + (*element..properties.*) +* `element.MultiSelect.properties.label` + (*element..properties.*) + +If none of the these keys exist, 'Known software' will be +displayed. The option properties lookup process is as the following: + +* `ApplicationForm.element.Software.properties.options.value1` + (*.element..properties.options.*) +* `element.Software.properties.options.value1` + (*element..properties.options.*) +* `ApplicationForm.element.Software.properties.options.value2` + (*.element..properties.options.*) +* `element.Software.properties.options.value2` + (*element..properties.options.*) + +If none of the these keys exist, 'TYPO3' will be displayed as +label for the first option and 'Neos' for the second option. + +.. _concepts-frontendrendering-translation-validationerrors: + +Translation of validation messages +---------------------------------- + +The translation of validation messages is similar to the translation of +`form definitions` abpve. The same translation files can be used. If the look-up +process does not find a key within the files, an Extbase message will be displayed. +EXT:form translates validators by default. + +The same as for `form definitions`, the translation keys are put together based on a +specific pattern. There is also a fallback chain. + +The following translation scenarios are possible: + +* translation of validation messages for a specific validator of a specific + form element (`elementIdentifier`) and specific form (`formDefinitionIdentifier`) +* translation of validation messages for a specific validator of various + form elements within a specific form (`formDefinitionIdentifier`) +* translation of validation messages for a specific validator of a specific + form element (`elementIdentifier`) in various forms +* translation of validation messages for a specific validator in various + forms + +In Extbase, validation messages are identified by numerical codes (UNIX +timestamps). Different codes can be used for the same validator. Read more about +:ref:`concrete validator configurations `. + +The look-up process searches for translation keys in the translation +files in the following order (the same order as the translation scenarios above): + +* `.validation.error..` +* `.validation.error.` +* `validation.error..` +* `validation.error.` + +.. _concepts-frontendrendering-translation-validation-example: + +Example Form Definition with Validator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: yaml + + identifier: ContactForm + type: Form + prototypeName: standard + label: 'Contact us' + + renderables: + - + identifier: Page1 + type: Page + label: 'Page 1' + + renderables: + - + identifier: LastName + type: Text + label: 'Last name' + properties: + fluidAdditionalAttributes: + required: required + validators: + - + identifier: NotEmpty + + +If a user submits this form without providing a last name, the `NotEmpty` +validator (at the bottom of the example above) fails and +sends 1221560910 as a ``. The system looks through the +translation keys in the following order searching for the `NotEmpty` validator for form element `LastName`: + +* ContactForm.validation.error.LastName.1221560910 (*.validation.error..*) +* ContactForm.validation.error.1221560910 (*.validation.error.*) +* validation.error.LastName.1221560910 (*validation.error..*) +* validation.error.1221560910 (validation*.error.*) + +As mentioned above, if no translation key is available, +a default Extbase framework message is displayed. + +.. _concepts-finishers-translation: +.. _concepts-frontendrendering-translation-finishers: + +Translation of finisher options +------------------------------- + +The translation of finisher options is similar to the translation of +`form definitions` above. The same translation files can be used. If the look-up +process does not find a key in the provided translation files, the property value +will be displayed unmodified. + +The same as for `form definitions`, the translation keys are put together based on a +specific pattern. There is also a fallback chain. + +The following translation scenarios are possible: + +* translation of finisher options for a specific finisher (`finisherIdentifier`) of a specific form (`formDefinitionIdentifier` below) +* translation of finisher options for a specific finisher (`finisherIdentifier`) of various forms + +The look-up process searches for translation keys in all the translation +files based on the following order (the same order as the translation scenarios above): + +* `.finisher..` +* `finisher..` + +The translation order is as follows: + +1. Default value from form definition +2. Overridden value from a FlexForm (if any) +3. Localized value provided by translation files (if any) + +The :yaml:`translation.propertiesExcludedFromTranslation` option skips the +third step so that the translation resolves to a FlexForm value if one exists. +For an example see +`Skip translation of overridden form finisher options `_. + +.. _concepts-frontendrendering-translation-finishers-example: + +Example Form Definition with Finisher +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: yaml + + identifier: ContactForm + type: Form + prototypeName: standard + label: 'Contact us' + + finishers: + - + identifier: Confirmation + options: + message: 'Thank you for your inquiry.' + + renderables: + ... + +The look-up process searches for the following translation keys for the +'Confirmation' finisher message option: + +* `ContactForm.finisher.Confirmation.message` (*.finisher..*) +* `finisher.Confirmation.message` (*finisher..*) + +If no translation key exists, the message 'Thank you for your inquiry.' will +be displayed. + + +.. _concepts-frontendrendering-translation-arguments: + +Form element translation arguments +================================== + +Form element property translations and finisher option translations can have +placeholders to output translation arguments. Translations can be enriched with +variable values by passing arguments to form element properties. This +feature was introduced in :issue:`81363`. + +.. _concepts-frontendrendering-translation-properties: + +Form element properties +----------------------- + +In the YAML form configuration you can add simple literal values: + +.. code-block:: yaml + + renderables: + - identifier: field-with-translation-arguments + type: Checkbox + label: This is a %s feature + renderingOptions: + translation: + translationFiles: + 10: path/to/locallang.xlf + arguments: + label: + - useful + +This will produce the label: `This is a useful feature`. + +Alternatively, you can use :typoscript:`formDefinitionOverrides` in TypoScript to set +translation arguments. One use case is a checkbox for +user confirmation which links to further information. Here it makes sense to use +YAML hashes (key value pairs) instead of YAML lists so that sections have keys. This simplifies +references in TypoScript since named keys are easy to read and can easily be reordered. With lists and numeric +keys the TypoScript setup would also need to be updated in this case. + +In the following form configuration example the list of :yaml:`renderables` has been replaced with +a hash of :yaml:`renderables`, and the field :yaml:`field-with-translation-arguments` +now has a named key :yaml:`fieldWithTranslationArguments`. This key can be anything +as long as it is unique at its level in the YAML - here just the :yaml:`identifier` +in another form: + +.. code-block:: yaml + + renderables: + fieldWithTranslationArguments: + identifier: field-with-translation-arguments + type: Checkbox + label: I agree to the terms and conditions + renderingOptions: + translation: + translationFiles: + 10: path/to/locallang.xlf + +If the label contains HTML markup - like in the above example - it must +be wrapped in `CDATA` tags in the :directory:`path/to/locallang.xlf` translation file, +to prevent analysis of character data by the parser. Also, the +label should be rendered using the :fluid:`` +ViewHelper in fluid templates, to prevent escaping of HTML tags: + +.. code-block:: xml + + + terms and conditions]]> + + +The TypoScript below can use the :typoscript:`fieldWithTranslationArguments` key to refer +to the field and adds a page URL as a translation argument for the link in the label: + +.. code-block:: typoscript + + plugin.tx_form { + settings { + formDefinitionOverrides { + { + renderables { + 0 { + # Page + renderables { + fieldWithTranslationArguments { + renderingOptions { + translation { + arguments { + label { + 0 = TEXT + 0.typolink { + # Terms and conditions page, could be + # set also via TypoScript constants + parameter = 42 + returnLast = url + } + } + } + } + } + } + } + } + } + } + } + } + } + +The :yaml:`Page` element of the form definition is not registered with a named key so a numeric +key :yaml:`0` is used which, as mentioned above, is prone to errors when more pages are added +or reordered. + +.. important:: + + There must be at least one translation file with a translation for the + form element property. Arguments are not inserted into default + values in a form definition. + +Finishers +--------- + +The same mechanism (YAML, YAML + TypoScript) works for finisher options: + +.. code-block:: yaml + + finishers: + finisherWithTranslationArguments: + identifier: EmailToReceiver + options: + subject: My %s subject + recipients: + your.company@example.com: 'Your Company name' + ceo@example.com: 'CEO' + senderAddress: bar@example.org + translation: + translationFiles: + 10: path/to/locallang.xlf + arguments: + subject: + - awesome + +This will produce `My awesome subject`. + +.. _concepts-frontendrendering-basiccodecomponents: + +Basic code components +===================== + +.. figure:: ../../Images/basic_code_components.png + :alt: Basic code components + + Basic code components + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition: + +TYPO3\\CMS\\Form\\Domain\\Model\\FormDefinition +----------------------------------------------- + +The class :php:`TYPO3\CMS\Form\Domain\Model\FormDefinition` encapsulates +a complete `form definition`, with all of its + +* pages, +* form elements, +* validation rules, and +* finishers which are executed when the form is submitted. + +The FormDefinition domain model is not modified when the form is executed. + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition-anatomy: + +The anatomy of a form +~~~~~~~~~~~~~~~~~~~~~ + +A `FormDefinition` domain model consists of multiple `Page` objects. +When a form is displayed, only one `Page` is visible at a time. +However, you can navigate back and forth between the pages. A +`Page` consists of multiple `FormElements` which represent input +fields, textareas, checkboxes, etc, on a page. The `FormDefinition` +domain model, `Page` and `FormElement` objects have `identifiers` +which must be unique for each ``, +i.e. the `FormDefinition` domain model and a `FormElement` object may +have the same `identifier` but two `FormElement` objects cannot have the same +identifier. + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition-anatomy-example: + +Example +""""""" + +You can create a :php:`FormDefinition` domain model by calling the API methods +on it, or you can use a :php:`FormFactory` to build the form from a different +representation format such as YAML. The example below calls API methods to +add a page to a :php:`FormDefinition` and then to add an element to the page: + +.. code-block:: php + + $formDefinition = GeneralUtility::makeInstance(FormDefinition::class, 'myForm'); + + $page1 = GeneralUtility::makeInstance(Page::class, 'page1'); + $formDefinition->addPage($page); + + // second argument is the of the form element + $element1 = GeneralUtility::makeInstance(GenericFormElement::class, 'title', 'Text'); + $page1->addElement($element1); + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition-createformusingabstracttypes: + +Creating a form using abstract form element types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use the :php:`TYPO3\CMS\Form\Domain\Model\FormDefinition::addPage()` +and :php:`TYPO3\CMS\Form\Domain\Model\FormElements\Page::addElement()` methods as above +and create the `Page` and `FormElement` objects manually, but it is often +better to use the corresponding *create* methods (:php:`TYPO3\CMS\Form\Domain\Model\FormDefinition::createPage()` +and :php:`TYPO3\CMS\Form\Domain\Model\FormElements\Page::createElement()`). +You only need to pass them an abstract `` such as `Text` +or `Page` and EXT:form will resolve the classname and set default values. + +The :ref:`simple example ` +shown above can then be rewritten as follows: + +.. code-block:: php + + // we will come back to this later on + $prototypeConfiguration = []; + + $formDefinition = GeneralUtility::makeInstance(FormDefinition::class, 'myForm', $prototypeConfiguration); + $page1 = $formDefinition->createPage('page1'); + $element1 = $page1->addElement('title', 'Text'); + +You might wonder how the system knows that the element `Text` is +implemented with a `GenericFormElement`. This is configured in the +:php:`$prototypeConfiguration`. To make the example from above actually work, +we need to add some meaningful values to :php:`$prototypeConfiguration`: + +.. code-block:: php + + $prototypeConfiguration = [ + 'formElementsDefinition' => [ + 'Page' => [ + 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page' + ], + 'Text' => [ + 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement' + ], + ], + ]; + +For each abstract ``, we have to add some +configuration. In the snippet above, we only define the `implementation +class name`. Apart from that, it is always possible to set default values +for all configuration options of such elements, as the following example +shows: + +.. code-block:: php + + $prototypeConfiguration = [ + 'formElementsDefinition' => [ + 'Page' => [ + 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\Page', + 'label' => 'This is the label of the page if nothing else is specified' + ], + 'Text' => [ + 'implementationClassName' => 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement', + 'label' = >'Default Label', + 'defaultValue' => 'Default form element value', + 'properties' => [ + 'placeholder' => 'Text that is shown if element is empty' + ], + ], + ], + ]; + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition-preconfiguredconfiguration: + +Using pre-configured $prototypeConfiguration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Often, it does not make sense to manually create the $prototypeConfiguration +array. Bigger parts of this array are pre-configured in the extensions's +YAML settings. The :php:`TYPO3\CMS\Form\Domain\Configuration\ConfigurationService` +contains helper methods which return the ready-to-use :php`$prototypeConfiguration`. + +.. _concepts-frontendrendering-basiccodecomponents-formdefinition-rednering: + +Rendering a FormDefinition +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To trigger the rendering of a :php:`FormDefinition` domain model, the current +:php:`TYPO3\CMS\Extbase\Mvc\Web\Request` needs to be bound to the +`FormDefinition`. This binding results in a :php:`TYPO3\CMS\Form\Domain\Runtime\FormRuntime` +object which contains the `Runtime State` of the form. Among other things, +this object includes the currently inserted values: + +.. code-block:: php + + // $currentRequest needs to be available. + // Inside a controller, you would use $this->request + $form = $formDefinition->bind($currentRequest); + // now, you can use the $form object to get information about the currently entered values, etc. + +.. _concepts-frontendrendering-basiccodecomponents-formruntime: + +TYPO3\\CMS\\Form\\Domain\\Runtime\\FormRuntime +---------------------------------------------- + +This class implements the runtime logic of a form, i.e. the class + +* decides which page is currently shown, +* determines the current values of the form +* triggers validation and property mappings. + +You generally receive an instance of this class by +calling :php:`TYPO3\CMS\Form\Domain\Model\FormDefinition::bind()`. + +.. _concepts-frontendrendering-basiccodecomponents-formruntime-render: + +Rendering a form +~~~~~~~~~~~~~~~~ + +Rendering a form is easy. Just call :php:`render()` on the :php:`FormRuntime`:: + +.. code-block:: php + + $form = $formDefinition->bind($request); + $renderedForm = $form->render(); + +.. _concepts-frontendrendering-basiccodecomponents-formruntime-accessingformvalues: + +Accessing form values +~~~~~~~~~~~~~~~~~~~~~ + +In order to get the values the user has entered into the form, you can +access the :php:`FormRuntime` object like an array. If a form element with the +identifier `firstName` exists, you can use :php:`$form['firstName']` to +retrieve its current value. You can set values the same way. + +.. _concepts-frontendrendering-basiccodecomponents-formruntime-renderinginternals: + +Rendering internals +~~~~~~~~~~~~~~~~~~~ + +The :php:`FormRuntime` inquires the :php:`FormDefinition` domain model regarding +the configured renderer (:php:`TYPO3\CMS\Form\Domain\Model\FormDefinition::getRendererClassName()`) +and then triggers :php:`render()` on this Renderer. + +This allows you to declaratively define how a form should be rendered. + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + rendererClassName: 'TYPO3\CMS\Form\Domain\Renderer\FluidFormRenderer' + +.. _concepts-frontendrendering-basiccodecomponents-fluidformrenderer: + +TYPO3\\CMS\\Form\\Domain\\Renderer\\FluidFormRenderer +----------------------------------------------------- + +This class is a :php:`TYPO3\CMS\Form\Domain\Renderer\RendererInterface` +implementation which used to render a :php:`FormDefinition` domain model. It +is the default :t3ext:`form` renderer. + +Learn more about +the :ref:`FluidFormRenderer Options`. + +.. _concepts-frontendrendering-codecomponents-customformelementimplementations: + +Custom form element implementations +----------------------------------- + +PSR-14 events are available at crucial points in the life cycle of a +`FormElement`. Most of the time, own class implementations are therefore +unnecessary. A custom form element can be defined by: + +* writing some configuration, and +* utilizing the standard implementation of :php:`TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement`. + +.. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + CustomFormElementIdentifier: + implementationClassName: 'TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement' + +With the provided PSR-14 events, this `FormElement` can now be manipulated at runtime. + +.. seealso:: + * :ref:`PSR-14 events overview for EXT:form ` – + tables of all events and registration instructions + * :ref:`Runtime manipulation events ` + +If you insist on your own implementation, the abstract class :php:`TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement` +offers a perfect entry point. In addition, we recommend checking-out :php:`TYPO3\CMS\Form\Domain\Model\Renderable\AbstractRenderable`. +All of your own form element implementations must be programmed to the +interface :php:`TYPO3\CMS\Form\Domain\Model\Renderable\RenderableInterface`. +It is a good idea to derive your implementation from :php:`TYPO3\CMS\Form\Domain\Model\FormElements\AbstractFormElement`. + +.. _concepts-frontendrendering-renderviewHelper: + +"render" viewHelper +=================== + +The `RenderViewHelper` is the actual starting point for form rendering and +not the typical Extbase Controller as you may know it. + +For more technical insights read more about the viewHelper's :ref:`arguments`. + +.. _concepts-frontendrendering-fluidtemplate: + +Render through FLUIDTEMPLATE (without controller) +------------------------------------------------- + +.. code-block:: typoscript + + tt_content.custom_content_element = COA_INT + tt_content.custom_content_element { + 20 = FLUIDTEMPLATE + 20 { + file = EXT:my_site_package/Resources/Private/Templates/CustomContentElement.html + settings { + persistenceIdentifier = EXT:my_site_package/Resources/Private/Forms/MyForm.yaml + } + extbase.pluginName = Formframework + extbase.controllerExtensionName = Form + extbase.controllerName = FormFrontend + extbase.controllerActionName = perform + } + } + +``my_site_package/Resources/Private/Templates/CustomContentElement.html``: + +.. code-block:: html + + + +.. _concepts-frontendrendering-extbase: + +Render within your own Extbase extension +---------------------------------------- + +It is straight forward. Use the `RenderViewHelper` like this and you are +done: + +.. code-block:: html + + + +Point the property `controllerAction` to the desired action name and +provide values for the other parameters displayed below (you might need +those). + +.. code-block:: yaml + + type: Form + identifier: 'example-form' + label: 'TYPO3 is cool' + prototypeName: standard + renderingOptions: + controllerAction: perform + addQueryString: false + argumentsToBeExcludedFromQueryString: [] + additionalParams: [] + + renderables: + ... + +.. note:: + + In general, you can override each and every `form definition` with the help + of TypoScript (see ':ref:`TypoScript overrides`'). + + When using the `RenderViewHelper`, there is a second way: + The ':ref:`overrideConfiguration`' parameter. + This way, you can override the form definition within your template. + Provide an according array as shown in the example below. + + .. code-block:: html + + + +.. _concepts-frontendrendering-programmatically: + +Build forms programmatically +============================ + +To learn more about this topic, head to the chapter ':ref:`Build forms programmatically`' +which is part of the API reference section. + +.. _concepts-frontendrendering-runtimemanipulation: + +Runtime manipulation +==================== + +.. _concepts-frontendrendering-runtimemanipulation-hooks: + +:t3ext:`form` implements a decent amount of events that allow the manipulation of +your forms during runtime. In this way, it is possible to, for example, + +* ... prefill form elements with values from your database, +* ... skip a whole page based on the value of a certain form element, +* ... mark a form element as mandatory depending of the chosen value of another + form element. + +Please check out the :ref:`PSR-14 events overview ` +for more details. + +.. _concepts-frontendrendering-runtimemanipulation-typoscriptoverrides: + +TypoScript overrides +-------------------- + +Each and every `form definition` can be overridden via TypoScript if the +:php:`FormFrontendController` of :t3ext:`form` is used to render the form. Normally, +this is the case if the form has been added to the page using the form +plugin or when rendering the form via :ref:`FLUIDTEMPLATE `. + +The overriding of settings with TypoScript's help takes place after the :ref:`custom finisher settings` +of the form plugin have been loaded. In this way, you are able to manipulate +the `form definition` for a single page. In doing so, the altered +`form definition` is passed to the :php:`RenderViewHelper` which then +generates the form programmatically. At this point, you can still change the +form elements using the above-mentioned concept of :ref:`hooks`. + +.. code-block:: typoscript + + plugin.tx_form { + settings { + formDefinitionOverrides { + { + renderables { + 0 { + renderables { + 0 { + label = TEXT + label.value = Overridden label + } + } + } + } + } + } + } + } diff --git a/Documentation/I/Concepts/Index.rst b/Documentation/I/Concepts/Index.rst new file mode 100644 index 0000000..6bce50a --- /dev/null +++ b/Documentation/I/Concepts/Index.rst @@ -0,0 +1,26 @@ +.. include:: /Includes.rst.txt + +.. _concepts: + +======== +Concepts +======== + +Within this chapter, you will learn the basic concepts of the form framework. +It addresses your concerns as backend editor and integrator. Some of the +chapters also cover topics for developers. + +.. toctree:: + + TargetGroupsAndMainPrinciples/Index + Configuration/Index + FormConfigurationFormDefinition/Index + FormFileStorages/Index + FrontendRendering/Index + Variants/Index + Validators/Index + Finishers/Index + FormManager/Index + FormEditor/Index + FormPlugin/Index + Autocomplete/Index diff --git a/Documentation/I/Concepts/TargetGroupsAndMainPrinciples/Index.rst b/Documentation/I/Concepts/TargetGroupsAndMainPrinciples/Index.rst new file mode 100644 index 0000000..da01410 --- /dev/null +++ b/Documentation/I/Concepts/TargetGroupsAndMainPrinciples/Index.rst @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-introduction: + +Target groups and main principles +================================= + +As :ref:`we saw in the introduction`, the ``form`` extension is a +framework where editors, integrators, and developers can +create and manage forms with different interfaces and functionality. + +The most important part of EXT:form is the backend ``form editor``. Different types of users +can use the ``form editor`` for different things. Integrators can manage HTML +class attributes, developers can create +complex ``form definitions`` and editors can edit properties. + +The form extension tries to find a compromise between these things. The +``form editor`` is mainly designed for editors, so simple, easy-to-edit properties are +displayed. However, the ``form editor`` can be easily extended by YAML configuration. + +And should this is not enough for your specific project, you can +integrate your own JavaScript code using the JavaScript API. + +You can create and define forms globally in the :guilabel:`Web->Forms` module or you can load forms +from inside extensions, for example, the ``Mail form`` content element. + +Some parts of a form can be overridden in the form plugin. This means you can +reuse the same form on different pages with a different configuration. + +The information in this chapter will show you that there are many ways to +customize the form framework, depending on your use case. Be creative and share +your solution with the TYPO3 community! + +This chapter describes the basics of the form framework. Check +out the reference and the examples to get a deeper understanding of +the framework. diff --git a/Documentation/I/Concepts/Validators/Index.rst b/Documentation/I/Concepts/Validators/Index.rst new file mode 100644 index 0000000..113091d --- /dev/null +++ b/Documentation/I/Concepts/Validators/Index.rst @@ -0,0 +1,294 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-validators: + +Validators +========== + +The form framework ships a set of server-side validators (derived from Extbase +validators) which you can use in form elements. Some validators can only +be used for certain elements, e.g. the "Date range validator" can only be used for +"Date" elements. Some form elements +(like "Email") come with validators. + +You can define your own validation error messages using the ``validationErrorMessages`` +property. These error messages can also be set in the form editor. + + +.. _concepts-validators-client-side-validation: + +Client-side validation +---------------------- + +In the form framework, HTML 5-based frontend validation can be added to form +elements, but JavaScript validation is not included. The TYPO3 core have no plans to +add this functionality at the current time. However, you can +add it yourself if required. Examples of reliable and well-maintained projects are +`Parsley `_ +and `jQuery Validation `__. + + +.. _concepts-validators-localization-client-side-validations: + +Localization of client side validation +"""""""""""""""""""""""""""""""""""""" + +Display of validation messages is browser-specific and not generated by TYPO3 so +these messages cannot easily be changed. However, you can use JavaScript to change +validation messages. See `Stack Overflow `__ +for more information. + + +.. _concepts-validators-server-side-validation: + +Server-side validation +---------------------- + + +.. _concepts-validators-alphanumeric: + +Alphanumeric validator (:yaml:`Alphanumeric`) +""""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Alphanumeric validator"` +checks for alphanumeric strings. Alphanumeric is defined as a combination of +alphabetic and numeric characters `[A-Z + 0-9]`. + + +.. _concepts-validators-count: + +Number of submitted values validator (:yaml:`Count`) +"""""""""""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Number of submitted values validator"` +checks if a value contains a specific number of elements. The +validator has two options: + +- Minimum [:yaml:`options.minimum`]: The minimum count to accept. +- Maximum [:yaml:`options.maximum`]: The maximum count to accept. + + +.. _concepts-validators-date_range: + +Date range validator (:yaml:`DateRange`) +"""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Date range validator"` +checks if a value is a valid DateTime object and within a specified +date range. The range can be defined by providing a minimum and/or maximum date. +The validator has two options: + +- Format [:yaml:`options.format`]: The format of the minimum and maximum option. + Default: [:yaml:`Y-m-d`]. +- Minimum date [:yaml:`options.minimum`]: The minimum date formatted as `Y-m-d`. +- Maximum date [:yaml:`options.maximum`]: The maximum date formatted as `Y-m-d`. + +The options :yaml:`minimum` and :yaml:`maximum` must have the format 'Y-m-d' which +represents the `RFC 3339 `__ +'full-date' format. + +The input must be a DateTime object. This input can be tested against a minimum +date and a maximum date. The minimum date and the maximum date are strings. The minimum +and maximum date can be configured through the validator options. + + +.. _concepts-validators-date_time: + +Date/time validator (:yaml:`DateTime`) +""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Date/time validator"` +checks if a value is a valid DateTime object. The date string is +expected to be formatted according to the `W3C standard `__ +which is `YYYY-MM-DDT##:##:##+##:##`, for example `2005-08-15T15:52:01+00:00`. + + +.. _concepts-validators-email: + +Email validator (:yaml:`EmailAddress`) +"""""""""""""""""""""""""""""""""""""" + +The :ref:`"Email validator"` +checks if a value is a valid email address. The format of a valid email +address is defined in `RFC 3696 `__. +This standard allows international characters and multiple +`@` signs. + + +.. _concepts-validators-filesize: + +File size validator (:yaml:`FileSize`) +"""""""""""""""""""""""""""""""""""""" + +The :ref:`"File size validator"` +validates the size of a file resource. The validator has two options: + +- Minimum [:yaml:`options.minimum`]: The minimum file size. Use the + format `B|K|M|G`. For example: `10M` is 10 Megabytes. +- Maximum [:yaml:`options.maximum`]: The maximum file size. Use the + format `B|K|M|G`. For example: `10M` is 10 Megabytes. + +Use the format `B|K|M|G` for file size, for example, `10M` +is 10 megabytes. Note: the maximum file size also depends on the :file:`php.ini` +settings of your environment. + + +.. _concepts-validators-floating_point: + +Floating-point number validator (:yaml:`Float`) +""""""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Floating-point number validator"` +checks if a value is of type float or a string matching the regular +expression `[0-9.e+-]`. + + +.. _concepts-validators-integer: + +Integer number validator (:yaml:`Integer`) +"""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Integer number validator"` +checks if a value is a valid integer. + + +.. _concepts-validators-empty: + +Empty validator (:yaml:`NotEmpty`) +"""""""""""""""""""""""""""""""""" + +The :ref:`"Empty validator"` +checks if a value is not empty (i.e. equal to NULL, empty string, empty array or empty +object). + + +.. _concepts-validators-number: + +Number validator (:yaml:`Number`) +""""""""""""""""""""""""""""""""" + +The :ref:`"Number validator"` +checks if a value is a number. + + +.. _concepts-validators-number_range: + +Number range validator (:yaml:`NumberRange`) +"""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Number range validator"` +checks if a value is a number in a specified range. The validator has +two options: + +- Minimum [:yaml:`options.minimum`]: The minimum value. +- Maximum [:yaml:`options.maximum`]: The maximum value. + + +.. _concepts-validators-regular_expressions: + +Regular expression validator (:yaml:`RegularExpression`) +"""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"Regular expression validator"` +checks if a value matches a specified regular expression. Delimiters +or modifiers are not supported. The validator has one option: + +- Regular expression [:yaml:`options.regularExpression`]: The regular expression + to use for validation, used as given. + +As an example, a user submits a domain name and the submitted value should only +contain the second and the top level domain, i.e. "typo3.org" instead of +"https://typo3.org". The regular expression for this would be :code:`/^[-a-z0-9]+\.[a-z]{2,6}$/`. + +.. _concepts-validators-string_length: + +String length validator (:yaml:`StringLength`) +"""""""""""""""""""""""""""""""""""""""""""""" + +The :ref:`"String length validator"` +checks if a value is a valid string and its length is within a specified +range. The validator has two options: + +- Minimum [:yaml:`options.minimum`]: The minimum length of a valid string. +- Maximum [:yaml:`options.maximum`]: The maximum length of a valid string. + + +.. _concepts-validators-text: + +Non-XML text validator (:yaml:`Text`) +""""""""""""""""""""""""""""""""""""" + +The :ref:`"Non-XML text validator"` +checks if a value is a valid piece of text (containing no XML tags). This basically +means that tags are stripped out. In this special case quotes are not encoded +(see `filter_var() `__ for more information. + +Be aware that the value of this check entirely depends on the output +context. The validated text is not expected to be secure. +If you want to be sure of that, use a customized regular expression or filter on +output. + + +.. _concepts-validators-validation-message-translation: + +Translation of validation messages +---------------------------------- + +To learn more about this topic, see :ref:`here`. + + +.. _concepts-validators-customvalidatorimplementations: + +Custom validator implementations +-------------------------------- + +Validators belong to configuration ``prototypes`` in a ``validatorsDefinition``. +Set the ``implementationClassName`` property of the ``prototype`` to your +own validator classes. + +.. code-block:: yaml + + prototypes: + standard: + validatorsDefinition: + Custom: + implementationClassName: 'VENDOR\MySitePackage\Domain\Validation\CustomValidator' + +Add ``options`` to your validator and provide a default value ``yourCustomOption``: + +.. code-block:: yaml + + prototypes: + standard: + validatorsDefinition: + Custom: + implementationClassName: 'VENDOR\MySitePackage\Domain\Validation\CustomValidator' + options: + yourCustomOption: 'Jurian' + +You can override the default value in your ``form definition``: + +.. code-block:: yaml + :emphasize-lines: 13 + + identifier: sample-form + label: 'Simple Contact Form' + prototype: standard + type: Form + + renderables: + - + identifier: subject + label: 'Name' + type: Text + validators: + - + identifier: Custom + options: + yourCustomOption: 'Mathias' + +As mentioned above, EXT:form uses Extbase validators. That said, +your own validators should extend :php:`\TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator`. +Read more in "TYPO3 Explained": +:ref:`t3coreapi:extbase_domain_validator`. diff --git a/Documentation/I/Concepts/Variants/Index.rst b/Documentation/I/Concepts/Variants/Index.rst new file mode 100644 index 0000000..ea3d385 --- /dev/null +++ b/Documentation/I/Concepts/Variants/Index.rst @@ -0,0 +1,686 @@ +.. include:: /Includes.rst.txt + + +.. _concepts-variants: + +Variants +======== + + +.. _concepts-variants-basics: + +Basics +------ + +A variant is an "alternative" form definition section that allows you to change +properties of form elements, validators, and finishers. Variants are activated +by conditions. This allows you to: + +* translate form element values depending on the frontend language +* set and remove validators from one form element depending on the + value of another form element +* hide entire steps (form pages) depending on the value of a form + element +* set finisher options depending on the value of a form element +* hide a form element in particular finishers and on the summary step + +Form element variants can be defined statically in +form definitions or created programmatically through an API. The +variants defined in a form definition are applied to +a form based on their conditions at runtime. Programmatically defined variants +can be applied at any time. + +Variant conditions can be evaluated programmatically +at any time. However, some conditions are only available at runtime, +for example, checking a form element value. + +Custom conditions and operators can be easily added. + +Only the form element properties listed in a variant are applied to the +form element, all other properties are retained. An exception to this +rule are finishers and validators. If finishers or validators are +**not** defined in a variant, the original finishers and validators +will be used. If at least one finisher or validator is defined in a +variant, the original finishers and validators are overwritten +by the finishers and validators in the variant. + +Variants defined in a form definition are **all** processed and +applied in the order of their matching conditions. This means if +variant 1 sets the label of a form element to "X" and variant 2 sets +the label to "Y", then variant 2 is applied, i.e. the label will be "Y". + +.. note:: + Currently it is **not** possible to define variants in + the backend form editor. + + +.. _concepts-variants-enabled-property: + +Rendering option ``enabled`` +---------------------------- + +The rendering option :yaml:`enabled` is available for all finishers and +form elements except the root form element and the first form +page. The option accepts a boolean value (:yaml:`true` or :yaml:`false`). + +Setting a form element to :yaml:`enabled: true` renders it in the +frontend and enables processing of its values, including property mapping +and validation. Setting :yaml:`enabled: false` disables it in the frontend. All +form elements and finishers except the root form element and the first form page can be enabled +or disabled. + +Setting a finisher to :yaml:`enabled: true` executes it when +the form is submitted. Setting :yaml:`enabled: false` skips the finisher. + +By default, :yaml:`enabled` is set to :yaml:`true`. + +See :ref:`examples` +below to learn more. + + +.. _concepts-variants-definition: + +Definition of variants +---------------------- + +Variants are defined at the form element level in YAML. Here is an example of a text +form element variant: + +.. code-block:: yaml + + type: Text + identifier: text-1 + label: Foo + variants: + - + identifier: variant-1 + condition: 'traverse(formValues, "checkbox-1") == 1' + # If the condition matches, the label property of the form + # element is set to the value 'Bar' + label: Bar + + +The :yaml:`identifier` must be unique at the form element level. + +Each variant has a single :yaml:`condition` which applies the variant if the +condition is satisfied. The +properties in the variant are applied to the form element. In the +example above the label of :yaml:`text-1` is +changed to ``Bar`` if the checkbox :yaml:`checkbox-1` is checked. + +The following properties can be overwritten by :yaml:`Form` (the topmost element) +variants: + +* :yaml:`label` +* :yaml:`renderingOptions` +* :yaml:`finishers` +* :yaml:`rendererClassName` + +The following properties can be overwritten by all other form element variants: + +* :yaml:`enabled` +* :yaml:`label` +* :yaml:`defaultValue` +* :yaml:`properties` +* :yaml:`renderingOptions` +* :yaml:`validators` + +.. note:: + Unset individual list items in select option variants by marking the values with + :code:`__UNSET`. See :ref:`example ` below. + +.. _concepts-variants-conditions: + +Conditions +---------- + +The form framework uses the Symfony component `expression language `_ +for conditions. An expression is a one-liner that returns a boolean value, for example, +:yaml:`applicationContext matches "#Production/Local#"`. For further information see +the `Symfony docs `_. +The form framework extends the expression language with variables to access +form values and environment settings. + +.. _concepts-variants-conditions-formruntime: + +``formRuntime`` (object) +^^^^^^^^^^^^^^^^^^^^^^^^ + +You can access every public method of :php:`\TYPO3\CMS\Form\Domain\Runtime\FormRuntime`. +Learn more :ref:`here`. + +For example: + +:yaml:`formRuntime.getIdentifier() == "test"`. + +.. _concepts-variants-conditions-renderable: + +``renderable`` (VariableRenderableInterface) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`renderable` contains the instance of renderable that the condition +is applied to. This can be used e.g. to access the identifier of the +current renderable without having to duplicate it. + +For example: + +:yaml:`traverse(formValues, renderable.getIdentifier()) == "special value"`. + +.. _concepts-variants-conditions-formvalues: + +``formValues`` (array) +^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`formValues` holds all the submitted form element values. Each +key in the array represents a form element identifier. + +For example: + +:yaml:`traverse(formValues, "text-1") == "yes"`. + +.. _concepts-variants-conditions-stepidentifier: + +``stepIdentifier`` (string) +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`stepIdentifier` is set to the :yaml:`identifier` of the current +step. + +For example: + +:yaml:`stepIdentifier == "page-1"`. + +.. _concepts-variants-conditions-steptype: + +``stepType`` (string) +^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`stepType` is set to the :yaml:`type` of the current step. + +For example: + +:yaml:`stepType == "SummaryPage"`. + +.. _concepts-variants-conditions-finisheridentifer: + +``finisherIdentifier`` (string) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`finisherIdentifier` is set to the :yaml:`identifier` of the +current finisher or an empty string (if no finishers are executed). + +For example: + +:yaml:`finisherIdentifier == "EmailToSender"`. + +.. _concepts-variants-conditions-site: + +``site`` (object) +^^^^^^^^^^^^^^^^^ + +You can access every public method in :php:`\TYPO3\CMS\Core\Site\Entity\Site`. +The following are the most important ones: + +* getSettings() / The site settings array +* getDefaultLanguage() / The default language object for the current site +* getConfiguration() / The whole configuration of the current site +* getIdentifier() / The identifier of the current site +* getBase() / The base URL of the current site +* getRootPageId() / The ID of the root page of the current site +* getLanguages() / An array of available languages for the current site +* getSets() / Configured site sets of a site (new in TYPO3 v13+) + +For example: + +:yaml:`site("settings").get("myVariable") == "something"`. +:yaml:`site("rootPageId") == "42"`. + +More details on the `Site` object can be found in +:ref:`Using site configuration in conditions `. + +.. _concepts-variants-conditions-sitelanguage: + +``siteLanguage`` (object) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can access every public method in :php:`\TYPO3\CMS\Core\Site\Entity\SiteLanguage`. +The most important ones are: + +* getLanguageId() / The sys_language_uid. +* getLocale() / The language locale, for example 'en_US.UTF-8'. +* getTypo3Language() / The language key for XLF files, for example, 'de' or 'default'. +* getTwoLetterIsoCode() / Returns the ISO-639-1 language ISO code, for example, 'de'. + +For example: + +:yaml:`siteLanguage("locale").getName() == "de-DE"`. + +.. _concepts-variants-conditions-applicationcontext: + +``applicationContext`` (string) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`applicationContext` is set to the application context +(@see GeneralUtility::getApplicationContext()). + +For example: + +:yaml:`applicationContext matches "#Production/Local#"`. + +.. _concepts-variants-conditions-contentobject: + +``contentObject`` (array) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +:yaml:`contentObject` contains the data of the current content object +or an empty array if no content object is available. + +For example: + +:yaml:`contentObject["pid"] in [23, 42]`. + + +.. _concepts-variants-programmatically: + +Working with variants programmatically +-------------------------------------- + +Create a variant with conditions through the PHP API:: + + /** @var TYPO3\CMS\Form\Domain\Model\Renderable\RenderableVariantInterface $variant */ + $variant = $formElement->createVariant([ + 'identifier' => 'variant-1', + 'condition' => 'traverse(formValues, "checkbox-1") == 1', + 'label' => 'foo', + ]); + + +Get all the variants of a form element:: + + /** @var TYPO3\CMS\Form\Domain\Model\Renderable\RenderableVariantInterface[] $variants */ + $variants = $formElement->getVariants(); + + +Apply a variant to a form element regardless of its conditions:: + + $formElement->applyVariant($variant); + + +.. _concepts-variants-examples: + +Examples +-------- + +Here are some more complex examples to show you what is possible with the +form framework. + + +.. _concepts-variants-examples-translation: + +Translation of form elements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this example, form, page and text elements have variants so that they are translated differently depending on +the frontend language (whether it is German or English). + +.. code-block:: yaml + :emphasize-lines: 9,10,24,25,40,41 + + type: Form + prototypeName: standard + identifier: contact-form + label: Kontaktformular + renderingOptions: + submitButtonLabel: Senden + variants: + - + identifier: language-variant-1 + condition: 'siteLanguage("locale").getName() == "en-US"' + label: Contact form + renderingOptions: + submitButtonLabel: Submit + renderables: + - + type: Page + identifier: page-1 + label: Kontaktdaten + renderingOptions: + previousButtonLabel: zurück + nextButtonLabel: weiter + variants: + - + identifier: language-variant-1 + condition: 'siteLanguage("locale").getName() == "en-US"' + label: Contact data + renderingOptions: + previousButtonLabel: Previous step + nextButtonLabel: Next step + renderables: + - + type: Text + identifier: text-1 + label: Vollständiger Name + properties: + fluidAdditionalAttributes: + placeholder: Ihre vollständiger Name + variants: + - + identifier: language-variant-1 + condition: 'siteLanguage("locale").getName() == "en-US"' + label: Full name + properties: + fluidAdditionalAttributes: + placeholder: Your full name + + +.. _concepts-variants-examples-validation: + +Adding validators dynamically +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this example, the :yaml:`email-address` field has a variant that adds validators +if :yaml:`checkbox-1` is checked. + + +.. code-block:: yaml + :emphasize-lines: 18,19 + + type: Form + prototypeName: standard + identifier: newsletter-subscription + label: Newsletter Subscription + renderables: + - + type: Page + identifier: page-1 + label: General data + renderables: + - + type: Text + identifier: email-address + label: Email address + defaultValue: + variants: + - + identifier: validation-1 + condition: 'traverse(formValues, "checkbox-1") == 1' + properties: + fluidAdditionalAttributes: + required: required + validators: + - + identifier: NotEmpty + - + identifier: EmailAddress + - + type: Checkbox + identifier: checkbox-1 + label: Check this and email will be mandatory + + +.. _concepts-variants-examples-hide-form-elements: + +Hide form elements +^^^^^^^^^^^^^^^^^^ + +In this example, the form element :yaml:`email-address` has +been enabled explicitly but this can be left out as this is +the default state. The form element :yaml:`text-3` has been disabled +to (temporarily) remove it from the form. The +field :yaml:`text-1` has a variant that hides it in all finishers and on the summary step. +The :yaml:`EmailToSender` finisher contains form values (:yaml:`email-address` +and :yaml:`name`). The :yaml:`EmailToSender` finisher is only enabled if +:yaml:`checkbox-1` has been checked by the user, otherwise it is skipped. + +.. code-block:: yaml + :emphasize-lines: 15,19,23,32,36,39,42,51 + + type: Form + prototypeName: standard + identifier: hidden-field-form + label: Hidden field form + finishers: + - + identifier: EmailToReceiver + options: + subject: Yes, I am ready + recipients: + your.company@example.com: 'Your Company name' + senderAddress: tritum@example.org + senderName: tritum@example.org + - + identifier: EmailToSender + options: + subject: This is a copy of the form data + recipients: + {email-address}: '{name}' + senderAddress: tritum@example.org + senderName: tritum@example.org + renderingOptions: + enabled: '{checkbox-1}' + renderables: + - + type: Page + identifier: page-1 + label: General data + renderables: + - + type: Text + identifier: text-1 + label: A field hidden on confirmation step and in all mails (finishers) + variants: + - + identifier: hide-1 + renderingOptions: + enabled: false + condition: 'stepType == "SummaryPage" || finisherIdentifier in ["EmailToSender", "EmailToReceiver"]' + - + type: Text + identifier: email-address + label: Email address + properties: + fluidAdditionalAttributes: + required: required + renderingOptions: + enabled: true + - + type: Text + identifier: text-3 + label: A temporarily disabled field + renderingOptions: + enabled: false + - + type: Checkbox + identifier: checkbox-1 + label: Check this and the sender gets an email + - + type: SummaryPage + identifier: summarypage-1 + label: Confirmation + + +.. _concepts-variants-examples-hide-steps: + +Hide steps +^^^^^^^^^^ + +In this example, the second step (:yaml:`page-2`) has a variant that disables it +if :yaml:`checkbox-1` is checked. :yaml:`checkbox-1` has a variant which +disables it on the summary step. + +.. code-block:: yaml + :emphasize-lines: 17, 21,22,24,27,31,32,34 + + type: Form + prototypeName: standard + identifier: multi-step-form + label: Muli step form + renderables: + - + type: Page + identifier: page-1 + label: First step + renderables: + - + type: Text + identifier: text-1 + label: A field + - + type: Checkbox + identifier: checkbox-1 + label: Check this and the next step will be skipped + variants: + - + identifier: variant-1 + condition: 'stepType == "SummaryPage"' + renderingOptions: + enabled: false + - + type: Page + identifier: page-2 + label: Second step + variants: + - + identifier: variant-2 + condition: 'traverse(formValues, "checkbox-1") == 1' + renderingOptions: + enabled: false + renderables: + - + type: Text + identifier: text-2 + label: Another field + - + type: SummaryPage + identifier: summarypage-1 + label: Confirmation + + +.. _concepts-variants-examples-finisher: + +Set finisher values dynamically +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this example, the form has a variant so that the finisher has different values +depending on the application context. + +.. code-block:: yaml + :emphasize-lines: 9,12,13,18 + + type: Form + prototypeName: standard + identifier: finisher-condition-example + label: Finishers under condition + finishers: + - + identifier: Confirmation + options: + message: I am NOT a local environment. + variants: + - + identifier: variant-1 + condition: 'applicationContext matches "#Production/Local#"' + finishers: + - + identifier: Confirmation + options: + message: I am a local environment. + renderables: + - + type: Page + identifier: page-1 + label: General data + renderables: + - + type: Text + identifier: text-1 + label: A field + + +.. _concepts-variants-examples-remove-options: + +Remove select options +^^^^^^^^^^^^^^^^^^^^^ + +In this example, a select form element has a variant which removes an option for +a specific locale. + +.. code-block:: yaml + :emphasize-lines: 13,24,25,28 + + type: Form + prototypeName: standard + identifier: option-remove-example + label: Options removed under condition + renderables: + - + type: Page + identifier: page-1 + label: Step + renderables: + - + identifier: salutation + type: SingleSelect + label: Salutation + properties: + options: + '': '---' + mr: Mr. + mrs: Mrs. + miss: Miss + defaultValue: '' + variants: + - + identifier: salutation-variant + condition: 'siteLanguage("locale").getName() == "zh-CN"' + properties: + options: + miss: __UNSET + + +.. _concepts-variants-custom-language-providers: + +Adding your own expression language providers +--------------------------------------------- + +You can extend the expression language with your own custom functions. For more +information see the official `docs `__ +and the appropriate :ref:`TYPO3 implementation details`. + +Register your own expression language provider class in +:file:`Configuration/ExpressionLanguage.php` and create it, making sure it +implements :php:`Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface`. + +.. code-block:: php + :caption: EXT:some_extension/Configuration/ExpressionLanguage.php + + return [ + 'form' => [ + Vendor\MyExtension\ExpressionLanguage\CustomExpressionLanguageProvider::class, + ], + ]; + +.. _concepts-variants-custom-language-variables: + +Adding your own expression language variables +--------------------------------------------- + +You can extend the expression language with your own variables. These +variables can be used in conditions. + +Register your own expression language provider class in +:file:`Configuration/ExpressionLanguage.php` as above and +and create it as follows: + +.. code-block:: php + :caption: EXT:some_extension/Classes/ExpressionLanguage/CustomExpressionLanguageProvider.php + + class CustomExpressionLanguageProvider extends AbstractProvider + { + public function __construct() + { + $this->expressionLanguageVariables = [ + 'variableA' => 'valueB', + ]; + } + } diff --git a/Documentation/I/Config/Index.rst b/Documentation/I/Config/Index.rst new file mode 100644 index 0000000..32966c2 --- /dev/null +++ b/Documentation/I/Config/Index.rst @@ -0,0 +1,17 @@ +.. include:: /Includes.rst.txt + + +.. _configurationreference: + +======================= +Configuration Reference +======================= + +This chapter is a complete reference of the possible configuration settings. +It addresses your concerns as and integrator and developer. + +.. toctree:: + + persistenceManager/Index + proto/Index + formManager/Index diff --git a/Documentation/I/Config/formManager/Index.rst b/Documentation/I/Config/formManager/Index.rst new file mode 100644 index 0000000..8181cd3 --- /dev/null +++ b/Documentation/I/Config/formManager/Index.rst @@ -0,0 +1,410 @@ +.. include:: /Includes.rst.txt + + +.. _formmanager: + +============= +[formManager] +============= + + +.. _formmanager-properties: + +Properties +========== + + +.. _formmanager.dynamicjavascriptmodules.app: + +dynamicJavaScriptModules.app +---------------------------- + +:aspect:`Option path` + formManager.dynamicJavaScriptModules.app + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + dynamicJavaScriptModules: + app: TYPO3/CMS/Form/Backend/FormManager + viewModel: TYPO3/CMS/Form/Backend/FormManager/ViewModel + +:aspect:`Description` + Internal setting. ES6 module specifier for the form manager JavaScript app. + + +.. _formmanager.dynamicjavascriptmodules.viewmodel: + +dynamicJavaScriptModules.viewModel +---------------------------------- + +:aspect:`Option path` + formManager.dynamicJavaScriptModules.viewModel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + dynamicJavaScriptModules: + app: '@typo3/form/backend/form-manager.js' + viewModel: '@typo3/form/backend/form-manager/view-model.js' + +:aspect:`Description` + Internal setting. ES6 module specifier for the form manager JavaScript view model. + + +.. _formmanager.stylesheets: + +stylesheets +----------- + +:aspect:`Option path` + formManager.stylesheets + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + stylesheets: + 100: 'EXT:form/Resources/Public/Css/form.css' + +:aspect:`Description` + Internal setting. Path for the form manager CSS file. + + +.. _formmanager.translationfiles: + +translationFiles +---------------- + +:aspect:`Option path` + formManager.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + +:aspect:`Good to know` + :ref:`Translate "Start template" options` + +:aspect:`Description` + The translation file(s) which should be used to translate parts of the form manager. + + +.. _formmanager.selectableprototypesconfiguration: + +selectablePrototypesConfiguration +--------------------------------- + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + selectablePrototypesConfiguration: + 100: + identifier: standard + label: formManager.selectablePrototypesConfiguration.standard.label + newFormTemplates: + 100: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.blankForm.label + 200: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.simpleContactForm.label + +:aspect:`Good to know` + - :ref:`"Start templates"` + - :ref:`Translate "Start template" options` + +:aspect:`Description` + Array with numerical Keys. Configure the ``Start template`` selection list within the ``form manager`` "Advanced settings" step. + + +.. _formmanager.selectableprototypesconfiguration.*.identifier: + +selectablePrototypesConfiguration.*.identifier +---------------------------------------------- + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration.*.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes ` + +:aspect:`Good to know` + - :ref:`"Start templates"` + +:aspect:`Description` + Reference to a ``prototype`` which should be used for the newly created form definition. + + +.. _formmanager.selectableprototypesconfiguration.*.label: + +selectablePrototypesConfiguration.*.label +----------------------------------------- + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration.*.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Good to know` + - :ref:`"Start templates"` + - :ref:`Translate "Start template" options` + +:aspect:`Description` + The ``Form prototype`` selectlist label for this ``prototype`` within the ``form manager`` "Advanced settings" step. + + +.. _formmanager.selectableprototypesconfiguration.*.newformtemplates: + +selectablePrototypesConfiguration.*.newFormTemplates +---------------------------------------------------- + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration.*.newFormTemplates + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + selectablePrototypesConfiguration: + 100: + identifier: standard + label: formManager.selectablePrototypesConfiguration.standard.label + newFormTemplates: + 100: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.blankForm.label + 200: + templatePath: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml' + label: formManager.selectablePrototypesConfiguration.standard.newFormTemplates.simpleContactForm.label + +:aspect:`Good to know` + - :ref:`"Start templates"` + - :ref:`Translate "Start template" options` + +:aspect:`Description` + Array with numerical Keys. Configure the ``Start templates`` selectlist for this ``prototype`` within the ``form manager`` "Advanced settings" step. + + +.. _formmanager.selectableprototypesconfiguration.*.newformtemplates.*.templatepath: + +selectablePrototypesConfiguration.*.newFormTemplates.*.templatePath +------------------------------------------------------------------- + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration.*.newFormTemplates.*.templatePath + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Good to know` + - :ref:`"Start templates"` + - :ref:`Translate "Start template" options` + +:aspect:`Description` + The filesystem path to the `Start template`` YAML file. + + +.. _formmanager.selectableprototypesconfiguration.*.newformtemplates.*.label: + +selectablePrototypesConfiguration.*.newFormTemplates.*.label +------------------------------------------------------------ + +:aspect:`Option path` + formManager.selectablePrototypesConfiguration.*.newFormTemplates.*.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Good to know` + - :ref:`"Start templates"` + - :ref:`Translate "Start template" options` + +:aspect:`Description` + The ``Start template`` selectlist label for this ``Start template`` within the ``form manager`` "Advanced settings" step. + + +.. _formmanager.controller: + +controller +---------- + +:aspect:`Option path` + formManager.controller + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + controller: + deleteAction: + errorTitle: formManagerController.deleteAction.error.title + errorMessage: formManagerController.deleteAction.error.body + +:aspect:`Description` + Internal setting. Configure the ``form manager`` flash message texts. + + +.. _formmanager.controller.deleteaction.errortitle: + +controller.deleteAction.errorTitle +---------------------------------- + +:aspect:`Option path` + formManager.controller.deleteAction.errorTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + controller: + deleteAction: + errorTitle: formManagerController.deleteAction.error.title + errorMessage: formManagerController.deleteAction.error.body + +:aspect:`Description` + Internal setting. Configure the ``form manager`` flash message texts. + + +.. _formmanager.controller.deleteaction.errormessage: + +controller.deleteAction.errorMessage +------------------------------------ + +:aspect:`Option path` + formManager.controller.deleteAction.errorMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + controller: + deleteAction: + errorTitle: formManagerController.deleteAction.error.title + errorMessage: formManagerController.deleteAction.error.body + +:aspect:`Description` + Internal setting. Configure the ``form manager`` flash message texts. diff --git a/Documentation/I/Config/persistenceManager/Index.rst b/Documentation/I/Config/persistenceManager/Index.rst new file mode 100644 index 0000000..acc111f --- /dev/null +++ b/Documentation/I/Config/persistenceManager/Index.rst @@ -0,0 +1,198 @@ +.. include:: /Includes.rst.txt + + +.. _persistencemanager: + +==================== +[persistenceManager] +==================== + + +.. _persistencemanager-properties: + +Properties +========== + +.. _persistencemanager.allowSaveToExtensionPaths: + +allowSaveToExtensionPaths +------------------------- + +:aspect:`Option path` + persistenceManager.allowSaveToExtensionPaths + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + persistenceManager: + allowSaveToExtensionPaths: false + +:aspect:`Good to know` + :ref:`Form/ File storages` + +:aspect:`Description` + Set this to ``true`` if you want to allow backend users to **edit** forms stored within your own extension. + + +.. _persistencemanager.allowDeleteFromExtensionPaths: + +allowDeleteFromExtensionPaths +----------------------------- + +:aspect:`Option path` + persistenceManager.allowDeleteFromExtensionPaths + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + persistenceManager: + allowDeleteFromExtensionPaths: false + +:aspect:`Good to know` + :ref:`Form/ File storages` + +:aspect:`Description` + Set this to ``true`` if you want to allow backend users to **delete** forms stored within your own extension. + + +.. _persistencemanager.sortByKeys: + +sortByKeys +----------------------------- + +:aspect:`Option path` + persistenceManager.sortByKeys + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + + persistenceManager: + sortByKeys: ['name', 'fileUid'] + +:aspect:`Good to know` + :ref:`Form/ File storages` + +:aspect:`Description` + The keys by which the forms should be sorted in the Form module and in the form plugin select. + + Valid keys, by which the forms can be sorted, are: + + ``name`` + The forms name. + + ``identifier`` + The filename. + + ``fileUid`` + The files uid. + + ``persistenceIdentifier`` + The files location. + + Example: ``1:/form_definitions/contact.form.yaml`` + + ``readOnly`` + Is the form readonly? + + ``removable`` + Is the form removable? + + ``location`` + Either `storage` or `extension` + + ``invalid`` + Does the form have an error? + + +.. _persistencemanager.sortAscending: + +sortAscending +----------------------------- + +:aspect:`Option path` + persistenceManager.sortAscending + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form manager) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + + persistenceManager: + sortAscending: true + +:aspect:`Good to know` + :ref:`Form/ File storages` + +:aspect:`Description` + If set to ``true``, the forms will be sorted in ascending, otherwise in descending order. + + +.. _persistencemanager.allowedExtensionPaths: + +allowedExtensionPaths +--------------------- + +:aspect:`Option path` + persistenceManager.allowedExtensionPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form manager/ form editor/ plugin) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + :ref:`Form/ File storages` + +:aspect:`Description` + Define the paths to folders which contain forms within your own extension. + For example: + + .. code-block:: yaml + + allowedExtensionPaths: + 10: EXT:my_site_package/Resources/Private/Forms/ diff --git a/Documentation/I/Config/proto/Index.rst b/Documentation/I/Config/proto/Index.rst new file mode 100644 index 0000000..48b2e3d --- /dev/null +++ b/Documentation/I/Config/proto/Index.rst @@ -0,0 +1,96 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes: + +============ +[prototypes] +============ + + +.. _prototypes-properties: + +Properties +========== + +.. _prototypes-properties-_prototypes: + +prototypes +---------- + +:aspect:`Option path` + prototypes + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form manager/ form editor/ plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + prototypes: + standard: + [...] + +:aspect:`Good to know` + - :ref:`"Prototypes"` + - :ref:`"Form configuration vs. form definition"` + +:aspect:`Description` + Array which defines the available prototypes. Every key within this array is called the ``prototypeIdentifier``. + + +.. _prototypes.prototypeIdentifier: + +prototypeIdentifier +--------------------- + +:aspect:`Option path` + prototypes. + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form manager/ form editor/ plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`"formManager.selectablePrototypesConfiguration.*.identifier"` + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + prototypes: + standard: + [...] + +:aspect:`Good to know` + - :ref:`"Prototypes"` + - :ref:`"Form configuration vs. form definition"` + +:aspect:`Description` + This array key identifies the `prototype``. Every ``form definition`` references to such a ```` through the property ``prototypeName``. + + +Subproperties +============= + +.. toctree:: + + form/Index + formElements/Index + finishersDefinition/Index + validatorsDefinition/Index + formEditor/Index + formEngine/Index diff --git a/Documentation/I/Config/proto/finishersDefinition/Index.rst b/Documentation/I/Config/proto/finishersDefinition/Index.rst new file mode 100644 index 0000000..922df2d --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/Index.rst @@ -0,0 +1,395 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition: + +===================== +[finishersDefinition] +===================== + + +.. _prototypes.prototypeIdentifier.finishersdefinition-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition-properties-finishersdefinition: + +[finishersDefinition] +--------------------- + +:aspect:`Option path` + prototypes..finishersDefinition + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + prototypes: + : + finishersDefinition: + [...] + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + Array which defines the available finishers. Every key within this array is called the ````. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier: + + +-------------------- + +:aspect:`Option path` + prototypes..finishersdefinition. + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + + prototypes: + standard: + Closure: + [...] + Confirmation: + [...] + EmailToSender: + [...] + EmailToReceiver: + [...] + DeleteUploads: + [...] + FlashMessage: + [...] + Redirect: + [...] + SaveToDatabase: + [...] + +:aspect:`Related options` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.formelementtypeidentifier.formEditor.propertyCollections.finishers.[*].identifier"` + - :ref:`"[FinishersEditor] selectOptions.[*].value"` + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + This array key identifies a finisher. This identifier could be used to attach a finisher to a form. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier-commonproperties: + +Common properties +============================================= + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition..implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.options: + +options +------- + +:aspect:`Option path` + prototypes..finishersDefinition..options + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + Array with finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.translation.translationFiles: + +translation.translationFiles +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition..translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Filesystem path(s) to translation files which should be searched for finisher translations. + If the property is undefined, - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Form.renderingOptions.translation.translationFiles"` will be used. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.formeditor: + +formEditor +---------- + +:aspect:`Option path` + prototypes..finishersDefinition..formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Array with configurations for the ``form editor`` + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition..formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition..formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition..formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: properties/predefinedDefaults.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.formengine: + +FormEngine +---------- + +:aspect:`Option path` + prototypes..finishersDefinition..FormEngine + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Array with configurations for the ``form plugin`` + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.FormEngine.label: + +FormEngine.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition..FormEngine.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: properties/formEngine/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier.FormEngine.elements: + +FormEngine.elements +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition..FormEngine.elements + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete finishers configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: properties/formEngine/elements.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.finisheridentifier-concreteconfigurations: + +Concrete configurations +======================= + +.. toctree:: + + finishers/Closure + finishers/Confirmation + finishers/EmailToReceiver + finishers/EmailToSender + finishers/DeleteUploads + finishers/FlashMessage + finishers/Redirect + finishers/SaveToDatabase diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/Closure.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/Closure.rst new file mode 100644 index 0000000..a9d5c51 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/Closure.rst @@ -0,0 +1,186 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure: + +========= +[Closure] +========= + + +.. _prototypes.prototypeIdentifier.finishersdefinitionclosure-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Closure.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Closure: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\ClosureFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure.options.closure: + +options.closure +--------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Closure.options.closure + +:aspect:`Data type` + \Closure + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + null + +.. :aspect:`Good to know` + ToDo + - :ref:`"Closure finisher"` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + The closure which is invoked if the finisher is triggered. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Closure.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Closure: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Closure.editor.header.label + predefinedDefaults: + options: + closure: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Closure.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Closure: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Closure.editor.header.label + predefinedDefaults: + options: + closure: '' + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.closure.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Closure.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Closure: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Closure.editor.header.label + predefinedDefaults: + options: + closure: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/Confirmation.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/Confirmation.rst new file mode 100644 index 0000000..b93e86b --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/Confirmation.rst @@ -0,0 +1,377 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation: + +============== +[Confirmation] +============== + +.. _prototypes.prototypeIdentifier.finishersdefinitionconfirmation-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Confirmation: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\ConfirmationFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.message: + +options.message +--------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.message + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + The form has been submitted. + +:aspect:`Good to know` + - :ref:`"Confirmation finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + The text which is shown if the finisher is invoked. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.contentelementuid: + +options.contentElementUid +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.contentElementUid + +:aspect:`Data type` + integer + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Description` + The option "contentElementUid" can be used to render a content element. + If contentElementUid is set, the option "message" will be ignored. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.typoscriptobjectpath: + +options.typoscriptObjectPath +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.typoscriptObjectPath + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 'lib.tx_form.contentElementRendering' + +:aspect:`Description` + The option "typoscriptObjectPath" can be used to render the content element (options.contentElementUid) through a typoscript lib. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.variables: + +options.variables +----------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.variables + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Description` + Variables which should be available within the template. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.templatename: + +options.templateName +-------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.templateName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + 'Confirmation' + +:aspect:`Description` + Define a custom template name which should be used. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.templaterootpaths: + +options.templateRootPaths +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.templateRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + Confirmation: + options: + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/Finishers/Confirmation/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layout/Finishers/Confirmation/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/Finishers/Confirmation/' + +:aspect:`Description` + Used to define several paths for templates, which will be tried in reversed order (the paths are searched from bottom to top). + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Confirmation finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.options.translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Confirmation finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Confirmation: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + predefinedDefaults: + options: + message: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Confirmation: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + predefinedDefaults: + options: + message: '' + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.confirmation.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Confirmation.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Confirmation: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + predefinedDefaults: + options: + message: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt + diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/DeleteUploads.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/DeleteUploads.rst new file mode 100644 index 0000000..05a6855 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/DeleteUploads.rst @@ -0,0 +1,114 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.deleteuploads: + +=============== +[DeleteUploads] +=============== + +.. _prototypes.prototypeIdentifier.finishersdefinitiondeleteuploads-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.deleteuploads.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.DeleteUploads.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + DeleteUploads: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\DeleteUploadsFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + Array which defines the available finishers. Every key within this array is called the ```` + + +.. _prototypes.prototypeIdentifier.finishersdefinition.deleteuploads.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.DeleteUploads.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + DeleteUploads: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.deleteuploads.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.DeleteUploads.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + DeleteUploads: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToReceiver.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToReceiver.rst new file mode 100644 index 0000000..f27c8d2 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToReceiver.rst @@ -0,0 +1,813 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver: + +================= +[EmailToReceiver] +================= + +.. _prototypes.prototypeIdentifier.finishersdefinitionemailtoreceiver-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + EmailToReceiver: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\EmailFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.subject: + +options.subject +--------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.subject + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Subject of the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.recipients: + +options.recipients +------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.recipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses and names of the recipients (To). + + The form editor in the backend module provides a visual UI to enter an arbitrary + amount of recipients. + + This option must contain a YAML hash with email addresses as keys and + recipient names as values: + + .. code-block:: yaml + + recipients: + first@example.org: First Recipient + second@example.org: Second Recipient + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.senderaddress: + +options.senderAddress +--------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.senderAddress + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email address of the sender/ visitor (From). + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.sendername: + +options.senderName +------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.senderName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty string + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Human-readable name of the sender. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.replytorecipients: + +options.replyToRecipients +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.replyToRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses of to be used as reply-to emails. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.carboncopyrecipients: + +options.carbonCopyRecipients +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.carbonCopyRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses of the copy recipient. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.blindcarbonCopyrecipients: + +options.blindCarbonCopyRecipients +--------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.blindCarbonCopyRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email address of the blind copy recipient. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.addhtmlpart: + +options.addHtmlPart +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.addHtmlPart + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + true + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + If set, mails will contain a plaintext and HTML part, otherwise only a + plaintext part. That way, it can be used to disable HTML and enforce + plaintext-only mails. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.attachuploads: + +options.attachUploads +--------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.attachUploads + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + true + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + If set, all uploaded items are attached to the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.title: + +options.title +------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.title + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The title, being shown in the email. The templates are based onFluidEmail. + The template renders the title field in the header section right above the + email body. Do not confuse this field with the subject of the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.translation.language: + +options.translation.language +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.translation.language + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If not set, the finisher options are translated depending on the current frontend language (if translations exists). + This option allows you to force translations for a given language isocode, e.g 'da' or 'de'. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.translation.translationFiles + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.partialrootpaths: + +options.partialRootPaths +------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.partialRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Fluid partial paths. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.layoutrootpaths: + +options.layoutRootPaths +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.layoutRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Fluid layout paths. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.options.variables: + +options.variables +----------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.options.variables + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Associative array of variables which are available inside the Fluid template. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + EmailToReceiver: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + EmailToReceiver: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + EmailToReceiver: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + predefinedDefaults: + options: + subject: '' + recipients: { } + senderAddress: '' + senderName: '' + replyToRecipients: { } + carbonCopyRecipients: { } + blindCarbonCopyRecipients: { } + addHtmlPart: true + attachUploads: true + translation: + language: 'default' + title: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.formengine.label: + +FormEngine.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.FormEngine.label + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + EmailToReceiver: + FormEngine: + label: tt_content.finishersDefinition.EmailToReceiver.label + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/label.rst.txt + + +@ToDo +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtoreceiver.formengine.elements: + +FormEngine.elements +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToReceiver.FormEngine.elements + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + EmailToReceiver: + FormEngine: + label: tt_content.finishersDefinition.EmailToReceiver.label + elements: + subject: + label: tt_content.finishersDefinition.EmailToReceiver.subject.label + config: + type: input + required: true + recipients: + title: tt_content.finishersDefinition.EmailToReceiver.recipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.recipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + senderAddress: + label: tt_content.finishersDefinition.EmailToReceiver.senderAddress.label + config: + type: input + required: true + senderName: + label: tt_content.finishersDefinition.EmailToReceiver.senderName.label + config: + type: input + replyToRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.replyToRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + carbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.carbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + blindCarbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToReceiver.blindCarbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + addHtmlPart: + label: tt_content.finishersDefinition.EmailToReceiver.addHtmlPart.label + config: + type: check + default: 1 + translation: + language: + label: tt_content.finishersDefinition.EmailToReceiver.language.label + config: + type: select + renderType: selectSingle + minitems: 1 + maxitems: 1 + size: 1 + items: + 10: + - tt_content.finishersDefinition.EmailToReceiver.language.1 + - default + title: + label: tt_content.finishersDefinition.EmailToReceiver.title.label + config: + type: input + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/elements.rst.txt diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToSender.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToSender.rst new file mode 100644 index 0000000..537cf73 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/EmailToSender.rst @@ -0,0 +1,812 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender: + +================= +[EmailToSender] +================= + +.. _prototypes.prototypeIdentifier.finishersdefinitionemailtosender-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + EmailToSender: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\EmailFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.subject: + +options.subject +--------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.subject + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Subject of the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.recipients: + +options.recipients +------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.recipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses and names of the recipients (To). + + The form editor in the backend module provides a visual UI to enter an arbitrary + amount of recipients. + + This option must contain a YAML hash with email addresses as keys and + recipient names as values: + + .. code-block:: yaml + + recipients: + first@example.org: First Recipient + second@example.org: Second Recipient + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.senderaddress: + +options.senderAddress +--------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.senderAddress + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email address of the sender/ visitor (From). + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.sendername: + +options.senderName +------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.senderName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty string + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Human-readable name of the sender. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.replytorecipients: + +options.replyToRecipients +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.replyToRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses of to be used as reply-to emails. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.carboncopyrecipients: + +options.carbonCopyRecipients +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.carbonCopyRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email addresses of the copy recipient. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.blindcarboncopyrecipients: + +options.blindCarbonCopyRecipients +--------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.blindCarbonCopyRecipients + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Email address of the blind copy recipient. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.addhtmlpart: + +options.addHtmlPart +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.addHtmlPart + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + true + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + If set, mails will contain a plaintext and HTML part, otherwise only a + plaintext part. That way, it can be used to disable HTML and enforce + plaintext-only mails. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.attachuploads: + +options.attachUploads +--------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.attachUploads + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + true + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + If set, all uploaded items are attached to the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.title: + +options.title +------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.title + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The title, being shown in the email. The templates are based onFluidEmail. + The template renders the title field in the header section right above the + email body. Do not confuse this field with the subject of the email. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.translation.language: + +options.translation.language +---------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.translation.language + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If not set, the finisher options are translated depending on the current frontend language (if translations exists). + This option allows you to force translations for a given language isocode, e.g 'da' or 'de'. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.translation.translationFiles + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.partialrootpaths: + +options.partialRootPaths +------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.partialRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Fluid layout paths. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.layoutrootpaths: + +options.layoutRootPaths +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.layoutRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Fluid partial paths. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.options.variables: + +options.variables +----------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.options.variables + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Email finisher"` + +:aspect:`Description` + Associative array of variables which are available inside the Fluid template. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + EmailToSender: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + EmailToSender: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + EmailToSender: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + predefinedDefaults: + options: + subject: '' + recipients: { } + senderAddress: '' + senderName: '' + replyToRecipients: { } + carbonCopyRecipients: { } + blindCarbonCopyRecipients: { } + addHtmlPart: true + attachUploads: true + translation: + language: 'default' + title: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.formengine.label: + +FormEngine.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.FormEngine.label + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + EmailToSender: + FormEngine: + label: tt_content.finishersDefinition.EmailToSender.label + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.emailtosender.formengine.elements: + +FormEngine.elements +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.EmailToSender.FormEngine.elements + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + EmailToSender: + FormEngine: + label: tt_content.finishersDefinition.EmailToSender.label + elements: + subject: + label: tt_content.finishersDefinition.EmailToSender.subject.label + config: + type: input + required: true + recipients: + title: tt_content.finishersDefinition.EmailToSender.recipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.recipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + senderAddress: + label: tt_content.finishersDefinition.EmailToSender.senderAddress.label + config: + type: input + required: true + senderName: + label: tt_content.finishersDefinition.EmailToSender.senderName.label + config: + type: input + replyToRecipients: + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.replyToRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + carbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.carbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + blindCarbonCopyRecipients: + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.label + type: array + section: true + sectionItemKey: email + sectionItemValue: name + el: + _arrayContainer: + type: array + title: tt_content.finishersDefinition.EmailToSender.blindCarbonCopyRecipients.item.label + el: + email: + label: tt_content.finishersDefinition.EmailToSender.recipients.email.label + config: + type: email + required: true + name: + label: tt_content.finishersDefinition.EmailToSender.recipients.name.label + config: + type: input + addHtmlPart: + label: tt_content.finishersDefinition.EmailToSender.addHtmlPart.label + config: + type: check + default: 1 + translation: + language: + label: tt_content.finishersDefinition.EmailToSender.language.label + config: + type: select + renderType: selectSingle + minitems: 1 + maxitems: 1 + size: 1 + items: + 10: + - tt_content.finishersDefinition.EmailToSender.language.1 + - default + title: + label: tt_content.finishersDefinition.EmailToSender.title.label + config: + type: input + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/elements.rst.txt diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/FlashMessage.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/FlashMessage.rst new file mode 100644 index 0000000..2557fe7 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/FlashMessage.rst @@ -0,0 +1,372 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage: + +============== +[FlashMessage] +============== + +.. _prototypes.prototypeIdentifier.finishersdefinitionflashmessage-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + FlashMessage: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\FlashMessageFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.messagebody: + +options.messageBody +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.messageBody + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + null + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + The flash message body TEXT. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.messagetitle: + +options.messageTitle +-------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.messageTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty string + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + The flash message title. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.messagearguments: + +options.messageArguments +------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.messageArguments + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty array + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + The flash message arguments, if needed. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.messagecode: + +options.messageCode +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.messageCode + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + null + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + +:aspect:`Description` + The flash message code, if needed. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.severity: + +options.severity +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.severity + +:aspect:`Data type` + Enum<\TYPO3\CMS\Core\Type\ContextualFeedbackSeverity>|int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + :php:`\TYPO3\CMS\Core\Type\ContextualFeedbackSeverity::OK` (0) + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + +:aspect:`Description` + The flash message severity code. + See :t3src:`core/Classes/Type/ContextualFeedbackSeverity.php` cases for the codes. + + Important: in YAML-based form definitions, the PHP enums cannot be used. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.options.translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"FlashMessage finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FlashMessage: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + predefinedDefaults: + options: + messageBody: '' + messageTitle: '' + messageArguments: '' + messageCode: 0 + severity: 0 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + FlashMessage: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + predefinedDefaults: + options: + messageBody: '' + messageTitle: '' + messageArguments: '' + messageCode: 0 + severity: 0 + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.flashmessage.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.FlashMessage.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + FlashMessage: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + predefinedDefaults: + options: + messageBody: '' + messageTitle: '' + messageArguments: '' + messageCode: 0 + severity: 0 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/Redirect.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/Redirect.rst new file mode 100644 index 0000000..62b600a --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/Redirect.rst @@ -0,0 +1,450 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect: + +========== +[Redirect] +========== + +.. _prototypes.prototypeIdentifier.finishersdefinitionredirect-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Redirect: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\RedirectFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.pageuid: + +options.pageUid +--------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.pageUid + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + 1 + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Redirect to this page uid. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.additionalparameters: + +options.additionalParameters +---------------------------- + +:aspect:`Option path` + prototypes.prototypeIdentifier.finishersDefinition.Redirect.options.additionalParameters + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty string + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Additional parameters which should be used on the target page. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.fragment: + +options.fragment +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.fragment + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty string + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Add a fragment (e.g. :html:`#c9` or :html:`#foo`) to the redirect link. + The :html:`#` character can be omitted. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.delay: + +options.delay +------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.delay + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 0 + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The redirect delay in seconds. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.statuscode: + +options.statusCode +------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.statusCode + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 303 + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The HTTP status code for the redirect. Default is "303 See Other". + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.options.translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Redirect finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Redirect: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + predefinedDefaults: + options: + pageUid: '' + additionalParameters: '' + fragment: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Redirect: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + predefinedDefaults: + options: + pageUid: '' + additionalParameters: '' + fragment: '' + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Redirect: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + predefinedDefaults: + options: + pageUid: '' + additionalParameters: '' + fragment: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.formengine.label: + +FormEngine.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.FormEngine.label + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Redirect: + FormEngine: + label: tt_content.finishersDefinition.Redirect.label + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.redirect.formengine.elements: + +FormEngine.elements +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.Redirect.FormEngine.elements + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Redirect: + FormEngine: + label: tt_content.finishersDefinition.Redirect.label + elements: + pageUid: + label: tt_content.finishersDefinition.Redirect.pageUid.label + config: + type: group + allowed: pages + size: 1 + minitems: 1 + maxitems: 1 + fieldWizard: + recordsOverview: + disabled: 1 + additionalParameters: + label: tt_content.finishersDefinition.Redirect.additionalParameters.label + config: + type: input + fragment: + label: tt_content.finishersDefinition.Redirect.fragment.label + config: + type: input + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + .. include:: ../properties/formEngine/elements.rst.txt + diff --git a/Documentation/I/Config/proto/finishersDefinition/finishers/SaveToDatabase.rst b/Documentation/I/Config/proto/finishersDefinition/finishers/SaveToDatabase.rst new file mode 100644 index 0000000..2520ec8 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/finishers/SaveToDatabase.rst @@ -0,0 +1,580 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase: + +================ +[SaveToDatabase] +================ + +.. _prototypes.prototypeIdentifier.finishersdefinitionsavetodatabase-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + SaveToDatabase: + implementationClassName: TYPO3\CMS\Form\Domain\Finishers\SaveToDatabaseFinisher + +:aspect:`Good to know` + - :ref:`"Custom finisher implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.table: + +options.table +------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.table + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + null + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Insert or update values into this table. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.mode: + +options.mode +------------ + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.mode + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 'insert' + +:aspect:`Possible values` + insert/ update + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + ``insert`` will create a new database row with the values from the submitted form and/or some predefined values. @see options.elements and options.databaseFieldMappings + + ``update`` will update a given database row with the values from the submitted form and/or some predefined values. 'options.whereClause' is then required. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.whereclause: + +options.whereClause +------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.whereClause + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes, if mode = update + +:aspect:`Default value` + empty array + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + This where clause will be used for a database update action. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements: + +options.elements +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + empty array + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Use ``options.elements`` to map form element values to existing database columns. + Each key within ``options.elements`` has to match with a form element identifier. + The value for each key within ``options.elements`` is an array with additional informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements..mapondatabasecolumn: + +options.elements..mapOnDatabaseColumn +------------------------------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements..mapOnDatabaseColumn + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The value from the submitted form element with the identifier ```` will be written into this database column. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements..savefileidentifierinsteadofuid: + +options.elements..saveFileIdentifierInsteadOfUid +------------------------------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements..saveFileIdentifierInsteadOfUid + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + false + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Set this to true if the database column should not be written if the value from the submitted form element with the identifier + ```` is empty (think about password fields etc.). + + This setting only rules for form elements which creates a FAL object like ``FileUpload`` or ``ImageUpload``. + By default, the uid of the FAL object will be written into the database column. Set this to true if you want to store the + FAL identifier (1:/user_uploads/some_uploaded_pic.jpg) instead. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements..skipifvalueisempty: + +options.elements..skipIfValueIsEmpty +------------------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements..skipIfValueIsEmpty + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + false + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Set this to true if the database column should not be written if the value from the submitted form element with the identifier + ```` is empty (think about password fields etc.). Empty means strings without content, whitespace + is valid content. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements..hashed: + +options.elements..hashed +------------------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements..hashed + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + false + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Set this to true if the value from the submitted form element should be hashed before writing into the database. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.elements..dateformat: + +options.elements..dateFormat +--------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.elements..dateFormat + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 'U' + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + If the internal Datatype is \DateTime which is true for the form element type "Date", + the object needs to be converted into a string value. + This option allows you to define the format of the date. + You can use every format accepted by PHP's date() function (https://php.net/manual/en/function.date.php#refsect1-function.date-parameters). + The default value is "U" which means a Unix timestamp. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.databasecolumnmappings: + +options.databaseColumnMappings +------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.databaseColumnMappings + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + empty array + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Use this to map database columns to static values. + Each key within ``options.databaseColumnMappings`` has to match with an existing database column. + The value for each key within ``options.databaseColumnMappings`` is an array with additional informations. + + This mapping is done *before* the ``options.element`` mapping. + This means if you map a database column to a value through ``options.databaseColumnMappings`` and map a submitted + form element value to the same database column through ``options.element``, the submitted form element value + will override the value you set within ``options.databaseColumnMappings``. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.databasecolumnmappings..value: + +options.databaseColumnMappings..value +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.databaseColumnMappings..value + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + The value which will be written to the database column. + You can also use the :ref:`FormRuntime accessor feature` to access every getable property from the ``FormRuntime`` + In short: use something like ``{}`` to get the value from the submitted form element with the identifier ````. + + If you use the FormRuntime accessor feature within ``options.databaseColumnMappings`` the functionality is nearly equal + to the ``options.elements`` configuration variant. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.databasecolumnmappings..skipifvalueisempty: + +options.databaseColumnMappings..skipIfValueIsEmpty +---------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.databaseColumnMappings..skipIfValueIsEmpty + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + +:aspect:`Description` + Set this to true if the database column should not be written if the value from `options.databaseColumnMappings. + .value` is empty. Empty means strings without content, whitespace is valid content. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.translation.propertiesExcludedFromTranslation: + +options.translation.propertiesExcludedFromTranslation +----------------------------------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.translation.propertiesExcludedFromTranslation + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + Localization from translation files will be skipped for all specified finisher options. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.options.translation.translationfiles: + +options.translation.translationFiles +------------------------------------ + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.options.translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"SaveToDatabase finisher"` + - :ref:`"Accessing form runtime values"` + - :ref:`"Translate finisher options"` + +:aspect:`Description` + If set, this translation file(s) will be used for finisher option translations. + If not set, the translation file(s) from the 'Form' element will be used. + Read :ref:`Translate finisher options` for more informations. + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SaveToDatabase: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + predefinedDefaults: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + SaveToDatabase: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + predefinedDefaults: + options: { } + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.finishersdefinition.savetodatabase.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..finishersDefinition.SaveToDatabase.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + SaveToDatabase: + formEditor: + iconIdentifier: form-finisher + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + predefinedDefaults: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/elements.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/elements.rst.txt new file mode 100644 index 0000000..6bf46f1 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/elements.rst.txt @@ -0,0 +1,6 @@ + + +Every array key must match to the related finisher option name. +For example, the - :ref:`"[Redirect] finisher"` has the option - :ref:`"pageUid"`. +If you want to make the ``pageUid`` overwritable within the ``form plugin``, then an array key ``pageUid`` has to exists within ``prototypes.prototypeIdentifier.finishersDefinition.finisheridentifier.FormEngine.elements``. +The configuration within ``prototypes.prototypeIdentifier.finishersDefinition.Redirect.FormEngine.elements.pageUid`` must follow the TCA syntax. diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/label.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/label.rst.txt new file mode 100644 index 0000000..05727e6 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/formEngine/label.rst.txt @@ -0,0 +1,5 @@ + + +Finisher options are overwritable within the ``form plugin``. +If the "Override finisher settings" checkbox is selected within the ``form plugin``, every finisher who has a - :ref:`"FormEngine"` configuration, is shown in a separate tab. +``label`` is the label for such a tab. diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/iconIdentifier.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/iconIdentifier.rst.txt new file mode 100644 index 0000000..f897f29 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/iconIdentifier.rst.txt @@ -0,0 +1,4 @@ + + +An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. +This icon will be shown within the - :ref:`"Inspector [CollectionElementHeaderEditor]"` if the finisher is selected. diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/implementationClassName.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/implementationClassName.rst.txt new file mode 100644 index 0000000..dca14af --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/implementationClassName.rst.txt @@ -0,0 +1,3 @@ + + +Classname which implements the finisher. diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/label.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/label.rst.txt new file mode 100644 index 0000000..9b71591 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/label.rst.txt @@ -0,0 +1,3 @@ + + +This label will be shown within the - :ref:`"Inspector [CollectionElementHeaderEditor]"` if the finisher is selected. diff --git a/Documentation/I/Config/proto/finishersDefinition/properties/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/finishersDefinition/properties/predefinedDefaults.rst.txt new file mode 100644 index 0000000..3221d31 --- /dev/null +++ b/Documentation/I/Config/proto/finishersDefinition/properties/predefinedDefaults.rst.txt @@ -0,0 +1,3 @@ + + +Defines predefined defaults for finisher options which are prefilled, if the finisher is added to a form. diff --git a/Documentation/I/Config/proto/form/Index.rst b/Documentation/I/Config/proto/form/Index.rst new file mode 100644 index 0000000..18a1b07 --- /dev/null +++ b/Documentation/I/Config/proto/form/Index.rst @@ -0,0 +1,325 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form: + +====== +[Form] +====== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.translation.translationfiles: +.. include:: renderingOptions/translation/translationFiles.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.templaterootpaths: +.. include:: renderingOptions/templateRootPaths.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.partialrootpaths: +.. include:: renderingOptions/partialRootPaths.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.layoutrootpaths: +.. include:: renderingOptions/layoutRootPaths.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.addquerystring: +.. include:: renderingOptions/addQueryString.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.argumentstobeexcludedfromquerystring: +.. include:: renderingOptions/argumentsToBeExcludedFromQueryString.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.additionalparams: +.. include:: renderingOptions/additionalParams.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.controlleraction: +.. include:: renderingOptions/controllerAction.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.httpmethod: +.. include:: renderingOptions/httpMethod.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.httpenctype: +.. include:: renderingOptions/httpEnctype.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.fluidadditionalattributes: +.. include:: renderingOptions/fluidAdditionalAttributes.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions._iscompositeformelement: +.. include:: renderingOptions/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions._istoplevelformelement: +.. include:: renderingOptions/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.honeypot.enable: +.. include:: renderingOptions/honeypot/enable.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.honeypot.formelementtouse: +.. include:: renderingOptions/honeypot/formElementToUse.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.submitbuttonlabel: +.. include:: renderingOptions/submitButtonLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.renderingoptions.skipunknownelements: +.. include:: renderingOptions/skipUnknownElements.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor: +.. include:: formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.editors.100: +.. include:: formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.editors.200: +.. include:: formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.editors.300: +.. include:: formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.editors.900: +.. include:: formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.predefineddefaults: +.. include:: formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor._iscompositeformelement: +.. include:: formEditor/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor._istoplevelformelement: +.. include:: formEditor/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.savesuccessflashmessagetitle: +.. include:: formEditor/saveSuccessFlashMessageTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.savesuccessflashmessagemessage: +.. include:: formEditor/saveSuccessFlashMessageMessage.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.saveerrorflashmessagetitle: +.. include:: formEditor/saveErrorFlashMessageTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.saveerrorflashmessagemessage: +.. include:: formEditor/saveErrorFlashMessageMessage.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalvalidationerrorsdialogtitle: +.. include:: formEditor/modalValidationErrorsDialogTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalvalidationerrorsconfirmButton: +.. include:: formEditor/modalValidationErrorsConfirmButton.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalinsertelementsdialogtitle: +.. include:: formEditor/modalInsertElementsDialogTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalinsertpagesdialogtitle: +.. include:: formEditor/modalInsertPagesDialogTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalclosedialogmessage: +.. include:: formEditor/modalCloseDialogMessage.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalclosedialogtitle: +.. include:: formEditor/modalCloseDialogTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalcloseconfirmbutton: +.. include:: formEditor/modalCloseConfirmButton.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalclosecancelbutton: +.. include:: formEditor/modalCloseCancelButton.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementdialogtitle: +.. include:: formEditor/modalRemoveElementDialogTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementdialogmessage: +.. include:: formEditor/modalRemoveElementDialogMessage.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementconfirmbutton: +.. include:: formEditor/modalRemoveElementConfirmButton.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementcancelbutton: +.. include:: formEditor/modalRemoveElementCancelButton.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementlastavailablepageflashmessagetitle: +.. include:: formEditor/modalRemoveElementLastAvailablePageFlashMessageTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.modalremoveelementlastavailablepageflashmessagemessage: +.. include:: formEditor/modalRemoveElementLastAvailablePageFlashMessageMessage.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.paginationtitle: +.. include:: formEditor/paginationTitle.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.iconidentifier: +.. include:: formEditor/iconIdentifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10: +.. include:: formEditor/propertyCollections/finishers/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.identifier: +.. include:: formEditor/propertyCollections/finishers/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.100: +.. include:: formEditor/propertyCollections/finishers/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.200: +.. include:: formEditor/propertyCollections/finishers/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.350: +.. include:: formEditor/propertyCollections/finishers/10/editors/350.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.500: +.. include:: formEditor/propertyCollections/finishers/10/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.600: +.. include:: formEditor/propertyCollections/finishers/10/editors/600.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.750: +.. include:: formEditor/propertyCollections/finishers/10/editors/750.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.850: +.. include:: formEditor/propertyCollections/finishers/10/editors/850.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.950: +.. include:: formEditor/propertyCollections/finishers/10/editors/950.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.1050: +.. include:: formEditor/propertyCollections/finishers/10/editors/1050.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.1100: +.. include:: formEditor/propertyCollections/finishers/10/editors/1100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.1200: +.. include:: formEditor/propertyCollections/finishers/10/editors/1200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.1400: +.. include:: formEditor/propertyCollections/finishers/10/editors/1400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.10.editors.9999: +.. include:: formEditor/propertyCollections/finishers/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20: +.. include:: formEditor/propertyCollections/finishers/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.identifier: +.. include:: formEditor/propertyCollections/finishers/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.100: +.. include:: formEditor/propertyCollections/finishers/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.200: +.. include:: formEditor/propertyCollections/finishers/20/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.350: +.. include:: formEditor/propertyCollections/finishers/20/editors/350.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.500: +.. include:: formEditor/propertyCollections/finishers/20/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.600: +.. include:: formEditor/propertyCollections/finishers/20/editors/600.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.750: +.. include:: formEditor/propertyCollections/finishers/20/editors/750.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.850: +.. include:: formEditor/propertyCollections/finishers/20/editors/850.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.950: +.. include:: formEditor/propertyCollections/finishers/20/editors/950.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.1050: +.. include:: formEditor/propertyCollections/finishers/20/editors/1050.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.1100: +.. include:: formEditor/propertyCollections/finishers/20/editors/1100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.1200: +.. include:: formEditor/propertyCollections/finishers/20/editors/1200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.1400: +.. include:: formEditor/propertyCollections/finishers/20/editors/1400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.20.editors.9999: +.. include:: formEditor/propertyCollections/finishers/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30: +.. include:: formEditor/propertyCollections/finishers/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.identifier: +.. include:: formEditor/propertyCollections/finishers/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.editors.100: +.. include:: formEditor/propertyCollections/finishers/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.editors.200: +.. include:: formEditor/propertyCollections/finishers/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.editors.300: +.. include:: formEditor/propertyCollections/finishers/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.editors.400: +.. include:: formEditor/propertyCollections/finishers/30/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.30.editors.9999: +.. include:: formEditor/propertyCollections/finishers/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.40: +.. include:: formEditor/propertyCollections/finishers/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.40.identifier: +.. include:: formEditor/propertyCollections/finishers/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.40.editors.100: +.. include:: formEditor/propertyCollections/finishers/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.40.editors.9999: +.. include:: formEditor/propertyCollections/finishers/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50: +.. include:: formEditor/propertyCollections/finishers/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50.identifier: +.. include:: formEditor/propertyCollections/finishers/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50.editors.100: +.. include:: formEditor/propertyCollections/finishers/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50.editors.200: +.. include:: formEditor/propertyCollections/finishers/50/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50.editors.300: +.. include:: formEditor/propertyCollections/finishers/50/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.50.editors.9999: +.. include:: formEditor/propertyCollections/finishers/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.60: +.. include:: formEditor/propertyCollections/finishers/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.60.identifier: +.. include:: formEditor/propertyCollections/finishers/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.60.editors.100: +.. include:: formEditor/propertyCollections/finishers/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.60.editors.9999: +.. include:: formEditor/propertyCollections/finishers/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.70: +.. include:: formEditor/propertyCollections/finishers/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.70.identifier: +.. include:: formEditor/propertyCollections/finishers/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.70.editors.100: +.. include:: formEditor/propertyCollections/finishers/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.70.editors.9999: +.. include:: formEditor/propertyCollections/finishers/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.80: +.. include:: formEditor/propertyCollections/finishers/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.80.identifier: +.. include:: formEditor/propertyCollections/finishers/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.80.editors.100: +.. include:: formEditor/propertyCollections/finishers/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.form.formeditor.propertycollections.finishers.80.editors.9999: +.. include:: formEditor/propertyCollections/finishers/80/editors/9999.rst.txt diff --git a/Documentation/I/Config/proto/form/formEditor.rst.txt b/Documentation/I/Config/proto/form/formEditor.rst.txt new file mode 100644 index 0000000..6a04ebe --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor.rst.txt @@ -0,0 +1,472 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Form: + formEditor: + predefinedDefaults: + renderingOptions: + submitButtonLabel: 'formEditor.elements.Form.editor.submitButtonLabel.value' + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.BaseFormElementMixin.editor.label.label + propertyPath: label + 300: + identifier: 'submitButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.editor.submitButtonLabel.label' + propertyPath: 'renderingOptions.submitButtonLabel' + 900: + identifier: finishers + templateName: Inspector-FinishersEditor + label: formEditor.elements.Form.editor.finishers.label + selectOptions: + 10: + value: '' + label: formEditor.elements.Form.editor.finishers.EmptyValue.label + 20: + value: EmailToSender + label: formEditor.elements.Form.editor.finishers.EmailToSender.label + 30: + value: EmailToReceiver + label: formEditor.elements.Form.editor.finishers.EmailToReceiver.label + 40: + value: Redirect + label: formEditor.elements.Form.editor.finishers.Redirect.label + 50: + value: DeleteUploads + label: formEditor.elements.Form.editor.finishers.DeleteUploads.label + 60: + value: Confirmation + label: formEditor.elements.Form.editor.finishers.Confirmation.label + _isCompositeFormElement: false + _isTopLevelFormElement: true + saveSuccessFlashMessageTitle: formEditor.elements.Form.saveSuccessFlashMessageTitle + saveSuccessFlashMessageMessage: formEditor.elements.Form.saveSuccessFlashMessageMessage + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage + modalValidationErrorsDialogTitle: formEditor.modals.validationErrors.dialogTitle + modalValidationErrorsConfirmButton: formEditor.modals.validationErrors.confirmButton + modalInsertElementsDialogTitle: formEditor.modals.insertElements.dialogTitle + modalInsertPagesDialogTitle: formEditor.modals.newPages.dialogTitle + modalCloseDialogMessage: formEditor.modals.close.dialogMessage + modalCloseDialogTitle: formEditor.modals.close.dialogTitle + modalCloseConfirmButton: formEditor.modals.close.confirmButton + modalCloseCancelButton: formEditor.modals.close.cancelButton + modalRemoveElementDialogTitle: formEditor.modals.removeElement.dialogTitle + modalRemoveElementDialogMessage: formEditor.modals.removeElement.dialogMessage + modalRemoveElementConfirmButton: formEditor.modals.removeElement.confirmButton + modalRemoveElementCancelButton: formEditor.modals.removeElement.cancelButton + modalRemoveElementLastAvailablePageFlashMessageTitle: formEditor.modals.removeElement.lastAvailablePageFlashMessageTitle + modalRemoveElementLastAvailablePageFlashMessageMessage: formEditor.modals.removeElement.lastAvailablePageFlashMessageMessage + paginationTitle: formEditor.pagination.title + iconIdentifier: content-form + propertyCollections: + finishers: + 10: + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToSender.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + identifier: EmailToSender + 20: + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + identifier: EmailToReceiver + 30: + identifier: Redirect + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + 200: + identifier: pageUid + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.pageUid.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel + browsableType: pages + propertyPath: options.pageUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: additionalParameters + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label + propertyPath: options.additionalParameters + 400: + identifier: fragment + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.fragment.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.fragment.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.fragment + description: formEditor.elements.Form.finisher.Redirect.editor.fragment.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: DeleteUploads + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Confirmation + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + 200: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.label + buttonLabel: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: IntegerOrEmpty + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.Confirmation.editor.message.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Closure + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Closure.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: FlashMessage + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: SaveToDatabase + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/form/formEditor/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/form/formEditor/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..0e37510 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/_isCompositeFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isCompositeFormElement +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + _isCompositeFormElement: false + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/form/formEditor/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/form/formEditor/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..d1a7fad --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/_isTopLevelFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isTopLevelFormElement +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + _isTopLevelFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/form/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..e9480a9 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/form/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/form/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..9e0830b --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.BaseFormElementMixin.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/form/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/form/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..5176740 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 300: + identifier: 'submitButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Form.editor.submitButtonLabel.label' + propertyPath: 'renderingOptions.submitButtonLabel' diff --git a/Documentation/I/Config/proto/form/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/form/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..ace1ffb --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/editors/900.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[FinishersEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 900: + identifier: finishers + templateName: Inspector-FinishersEditor + label: formEditor.elements.Form.editor.finishers.label + selectOptions: + 10: + value: '' + label: formEditor.elements.Form.editor.finishers.EmptyValue.label + 20: + value: EmailToSender + label: formEditor.elements.Form.editor.finishers.EmailToSender.label + 30: + value: EmailToReceiver + label: formEditor.elements.Form.editor.finishers.EmailToReceiver.label + 40: + value: Redirect + label: formEditor.elements.Form.editor.finishers.Redirect.label + 50: + value: DeleteUploads + label: formEditor.elements.Form.editor.finishers.DeleteUploads.label + diff --git a/Documentation/I/Config/proto/form/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..df50a94 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + iconIdentifier: content-form + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/form/formEditor/modalCloseCancelButton.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalCloseCancelButton.rst.txt new file mode 100644 index 0000000..9a95ac4 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalCloseCancelButton.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalCloseCancelButton +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalCloseCancelButton + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalCloseCancelButton: formEditor.modals.close.cancelButton + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalCloseConfirmButton.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalCloseConfirmButton.rst.txt new file mode 100644 index 0000000..a9bca9b --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalCloseConfirmButton.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalCloseConfirmButton +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalCloseConfirmButton + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalCloseConfirmButton: formEditor.modals.close.confirmButton + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalCloseDialogMessage.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalCloseDialogMessage.rst.txt new file mode 100644 index 0000000..46a5a46 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalCloseDialogMessage.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalCloseDialogMessage +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalCloseDialogMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalCloseDialogMessage: formEditor.modals.close.dialogMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalCloseDialogTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalCloseDialogTitle.rst.txt new file mode 100644 index 0000000..f541676 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalCloseDialogTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalCloseDialogTitle +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalCloseDialogTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalCloseDialogTitle: formEditor.modals.close.dialogTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalInsertElementsDialogTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalInsertElementsDialogTitle.rst.txt new file mode 100644 index 0000000..b06df4f --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalInsertElementsDialogTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalInsertPagesDialogTitle +-------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalInsertPagesDialogTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalInsertElementsDialogTitle: formEditor.modals.insertElements.dialogTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalInsertPagesDialogTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalInsertPagesDialogTitle.rst.txt new file mode 100644 index 0000000..10ff90c --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalInsertPagesDialogTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalInsertPagesDialogTitle +-------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalInsertPagesDialogTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalInsertPagesDialogTitle: formEditor.modals.newPages.dialogTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementCancelButton.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementCancelButton.rst.txt new file mode 100644 index 0000000..764d459 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementCancelButton.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementCancelButton +----------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementCancelButton + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementCancelButton: formEditor.modals.removeElement.cancelButton + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementConfirmButton.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementConfirmButton.rst.txt new file mode 100644 index 0000000..c82b093 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementConfirmButton.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementConfirmButton +------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementConfirmButton + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementConfirmButton: formEditor.modals.removeElement.confirmButton + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogMessage.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogMessage.rst.txt new file mode 100644 index 0000000..59a1e8e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogMessage.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementDialogMessage +------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementDialogMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementDialogMessage: formEditor.modals.removeElement.dialogMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogTitle.rst.txt new file mode 100644 index 0000000..0568ae4 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementDialogTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementDialogTitle +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementDialogTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementDialogTitle: formEditor.modals.removeElement.dialogTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageMessage.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageMessage.rst.txt new file mode 100644 index 0000000..8c09c0e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageMessage.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementLastAvailablePageFlashMessageMessage +----------------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementLastAvailablePageFlashMessageMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementLastAvailablePageFlashMessageMessage: formEditor.modals.removeElement.lastAvailablePageFlashMessageMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageTitle.rst.txt new file mode 100644 index 0000000..3c3651c --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalRemoveElementLastAvailablePageFlashMessageTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalRemoveElementLastAvailablePageFlashMessageTitle +--------------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalRemoveElementLastAvailablePageFlashMessageTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalRemoveElementLastAvailablePageFlashMessageTitle: formEditor.modals.removeElement.lastAvailablePageFlashMessageTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsConfirmButton.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsConfirmButton.rst.txt new file mode 100644 index 0000000..b8e8342 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsConfirmButton.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalValidationErrorsConfirmButton +--------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalValidationErrorsConfirmButton + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalValidationErrorsConfirmButton: formEditor.modals.validationErrors.confirmButton + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsDialogTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsDialogTitle.rst.txt new file mode 100644 index 0000000..c3e639d --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/modalValidationErrorsDialogTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.modalValidationErrorsDialogTitle +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.modalValidationErrorsDialogTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + modalValidationErrorsDialogTitle: formEditor.modals.validationErrors.dialogTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/paginationTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/paginationTitle.rst.txt new file mode 100644 index 0000000..87b153f --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/paginationTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.paginationTitle +-------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.paginationTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + paginationTitle: formEditor.pagination.title + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/form/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..47f6d0a --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Form: + formEditor: + predefinedDefaults: + renderingOptions: + submitButtonLabel: 'formEditor.elements.Form.editor.submitButtonLabel.value' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10.rst.txt new file mode 100644 index 0000000..8bc1eba --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10.rst.txt @@ -0,0 +1,167 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.10 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToSender.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/100.rst.txt new file mode 100644 index 0000000..9407c54 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1050.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1050.rst.txt new file mode 100644 index 0000000..0440fec --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1050.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.1050 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.1050 + +:aspect:`Data type` + array/ :ref:`[CheckboxEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToSender.editor.addHtmlPart.description + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1100.rst.txt new file mode 100644 index 0000000..25a1aa5 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1100.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.1100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.1100 + +:aspect:`Data type` + array/ :ref:`[CheckboxEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.attachUploads.label + propertyPath: options.attachUploads + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1200.rst.txt new file mode 100644 index 0000000..61c7c33 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.1200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.1200 + +:aspect:`Data type` + array/ :ref:`[SingleSelectEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToSender.editor.language.1 + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1400.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1400.rst.txt new file mode 100644 index 0000000..9e896a7 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/1400.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.1400 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.1400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToSender.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/200.rst.txt new file mode 100644 index 0000000..4305115 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.200 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/350.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/350.rst.txt new file mode 100644 index 0000000..c76c23b --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/350.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.350 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.350 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/500.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/500.rst.txt new file mode 100644 index 0000000..65d74d0 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/500.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.500 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/600.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/600.rst.txt new file mode 100644 index 0000000..0ef5d42 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/600.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.600 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.600 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/750.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/750.rst.txt new file mode 100644 index 0000000..8e7089a --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/750.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.750 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.750 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/850.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/850.rst.txt new file mode 100644 index 0000000..9239dcf --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/850.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.850 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.850 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/950.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/950.rst.txt new file mode 100644 index 0000000..5c59ae1 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/950.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.950 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.950 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToSender.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/9999.rst.txt new file mode 100644 index 0000000..3171d7d --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.10.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/identifier.rst.txt new file mode 100644 index 0000000..b49c318 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.10.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20.rst.txt new file mode 100644 index 0000000..a2edeb9 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20.rst.txt @@ -0,0 +1,167 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.20 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.description + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label + propertyPath: options.attachUploads + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1 + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/100.rst.txt new file mode 100644 index 0000000..30f73a2 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1050.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1050.rst.txt new file mode 100644 index 0000000..e406a11 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1050.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.1050 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.1050 + +:aspect:`Data type` + array/ :ref:`[CheckboxEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 1050: + identifier: addHtmlPart + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.label + propertyPath: options.addHtmlPart + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.addHtmlPart.description + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1100.rst.txt new file mode 100644 index 0000000..c1162b2 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1100.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.1100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.1100 + +:aspect:`Data type` + array/ :ref:`[CheckboxEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 1100: + identifier: attachUploads + templateName: Inspector-CheckboxEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.attachUploads.label + propertyPath: options.attachUploads + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1200.rst.txt new file mode 100644 index 0000000..a591a4d --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.1200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.1200 + +:aspect:`Data type` + array/ :ref:`[SingleSelectEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 1200: + identifier: language + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.label + propertyPath: options.translation.language + selectOptions: + 10: + value: default + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.language.1 + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1400.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1400.rst.txt new file mode 100644 index 0000000..72ac2b9 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/1400.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.1400 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.1400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 10: + identifier: EmailToSender + editors: + 1400: + identifier: title + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.label + propertyPath: options.title + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.title.description + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/200.rst.txt new file mode 100644 index 0000000..46d1e23 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.200 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 200: + identifier: subject + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.subject.label + propertyPath: options.subject + enableFormelementSelectionButton: true + propertyValidators: + 10: NotEmpty + 20: FormElementIdentifierWithinCurlyBracesInclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/350.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/350.rst.txt new file mode 100644 index 0000000..b389b31 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/350.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.350 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.350 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 350: + identifier: recipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.label + propertyPath: options.recipients + propertyValidators: + 10: NotEmpty + description: formEditor.elements.Form.finisher.EmailToReceiver.editor.recipients.description + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/500.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/500.rst.txt new file mode 100644 index 0000000..00e4303 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/500.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.500 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 500: + identifier: senderAddress + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderAddress.label + propertyPath: options.senderAddress + enableFormelementSelectionButton: true + propertyValidatorsMode: OR + propertyValidators: + 10: NaiveEmail + 20: FormElementIdentifierWithinCurlyBracesExclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/600.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/600.rst.txt new file mode 100644 index 0000000..492c9b7 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/600.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.600 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.600 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 600: + identifier: senderName + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.senderName.label + propertyPath: options.senderName + enableFormelementSelectionButton: true + propertyValidators: + 10: FormElementIdentifierWithinCurlyBracesInclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/750.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/750.rst.txt new file mode 100644 index 0000000..b303514 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/750.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.750 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.750 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 750: + identifier: replyToRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.replyToRecipients.label + propertyPath: options.replyToRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/850.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/850.rst.txt new file mode 100644 index 0000000..bb4e160 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/850.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.850 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.850 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 850: + identifier: carbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.carbonCopyRecipients.label + propertyPath: options.carbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/950.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/950.rst.txt new file mode 100644 index 0000000..a2f340a --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/950.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.950 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.950 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 950: + identifier: blindCarbonCopyRecipients + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.Form.finisher.EmailToReceiver.editor.blindCarbonCopyRecipients.label + propertyPath: options.blindCarbonCopyRecipients + isSortable: true + enableAddRow: true + enableDeleteRow: true + useLabelAsFallbackValue: false + gridColumns: + - + name: value + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.value.title + enableFormelementSelectionButton: true + - + name: label + title: formEditor.elements.Form.finisher.EmailToSender.editor.recipients.gridColumns.label.title + enableFormelementSelectionButton: true + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/9999.rst.txt new file mode 100644 index 0000000..763411e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.20.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/identifier.rst.txt new file mode 100644 index 0000000..4edc5af --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/20/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.20.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 20: + identifier: EmailToReceiver + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30.rst.txt new file mode 100644 index 0000000..1a0cbbe --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30.rst.txt @@ -0,0 +1,61 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.30 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + 200: + identifier: pageUid + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.pageUid.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel + browsableType: pages + propertyPath: options.pageUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: additionalParameters + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label + propertyPath: options.additionalParameters + 400: + identifier: fragment + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.fragment.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.fragment.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.fragment + description: formEditor.elements.Form.finisher.Redirect.editor.fragment.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/100.rst.txt new file mode 100644 index 0000000..64cafb5 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.30.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Redirect.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/200.rst.txt new file mode 100644 index 0000000..3cd48a8 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/200.rst.txt @@ -0,0 +1,41 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.30.editors.200 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[Typo3WinBrowserEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 200: + identifier: pageUid + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.pageUid.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.pageUid.buttonLabel + browsableType: pages + propertyPath: options.pageUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/300.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/300.rst.txt new file mode 100644 index 0000000..603346a --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/300.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.30.editors.300 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 300: + identifier: additionalParameters + templateName: Inspector-TextEditor + label: formEditor.elements.Form.finisher.Redirect.editor.additionalParameters.label + propertyPath: options.additionalParameters + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/400.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/400.rst.txt new file mode 100644 index 0000000..6c42288 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/400.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.30.editors.400 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 400: + identifier: fragment + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Redirect.editor.fragment.label + buttonLabel: formEditor.elements.Form.finisher.Redirect.editor.fragment.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.fragment + description: formEditor.elements.Form.finisher.Redirect.editor.fragment.description diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/9999.rst.txt new file mode 100644 index 0000000..a8abb15 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.30.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/identifier.rst.txt new file mode 100644 index 0000000..1d9f595 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/30/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.30.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 30: + identifier: Redirect + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40.rst.txt new file mode 100644 index 0000000..2de95de --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.40 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 40: + identifier: DeleteUploads + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/100.rst.txt new file mode 100644 index 0000000..c7ce719 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.40.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 40: + identifier: DeleteUploads + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.DeleteUploads.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/9999.rst.txt new file mode 100644 index 0000000..e5e2082 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.40.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 40: + identifier: DeleteUploads + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/identifier.rst.txt new file mode 100644 index 0000000..69cf82a --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.40.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 40: + identifier: DeleteUploads + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50.rst.txt new file mode 100644 index 0000000..cc517c6 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.50 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + 200: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.label + buttonLabel: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: IntegerOrEmpty + 20: FormElementIdentifierWithinCurlyBracesExclusive + 300: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.Confirmation.editor.message.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/100.rst.txt new file mode 100644 index 0000000..ce26db5 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.50.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/200.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/200.rst.txt new file mode 100644 index 0000000..83aba2e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/200.rst.txt @@ -0,0 +1,42 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.50.editors.200 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50.editors.200 + +:aspect:`Data type` + array/ :ref:`[Typo3WinBrowserEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 200: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.label + buttonLabel: formEditor.elements.Form.finisher.Confirmation.editor.contentElement.buttonLabel + browsableType: tt_content + iconIdentifier: mimetypes-x-content-text + propertyPath: options.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: IntegerOrEmpty + 20: FormElementIdentifierWithinCurlyBracesExclusive + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/300.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/300.rst.txt new file mode 100644 index 0000000..f3bc93d --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/300.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.50.editors.300 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextareaEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 300: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.message.label + propertyPath: options.message + description: formEditor.elements.Form.finisher.Confirmation.editor.message.description + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/9999.rst.txt new file mode 100644 index 0000000..d80cbd7 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.50.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/identifier.rst.txt new file mode 100644 index 0000000..02099ba --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/50/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.50.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60.rst.txt new file mode 100644 index 0000000..3b186e7 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.60 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 60: + identifier: Closure + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Closure.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/100.rst.txt new file mode 100644 index 0000000..52a835e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.60.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 60: + identifier: Closure + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.Closure.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/9999.rst.txt new file mode 100644 index 0000000..d955f67 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.60.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 60: + identifier: Closure + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/identifier.rst.txt new file mode 100644 index 0000000..0c190ac --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/60/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.60.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 60: + identifier: Closure + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70.rst.txt new file mode 100644 index 0000000..b8ff527 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.70 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 70: + identifier: FlashMessage + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/100.rst.txt new file mode 100644 index 0000000..b56f535 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.70.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 70: + identifier: FlashMessage + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.FlashMessage.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/9999.rst.txt new file mode 100644 index 0000000..2a3f1b5 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.70.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 70: + identifier: FlashMessage + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/identifier.rst.txt new file mode 100644 index 0000000..8a8d0c1 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.70.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 70: + identifier: FlashMessage + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80.rst.txt new file mode 100644 index 0000000..bf88a2e --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.80 +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Form: + formEditor: + propertyCollections: + finishers: + 80: + identifier: SaveToDatabase + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/100.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/100.rst.txt new file mode 100644 index 0000000..4f0cfe9 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.80.editors.100 +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 80: + identifier: SaveToDatabase + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.Form.finisher.SaveToDatabase.editor.header.label + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/9999.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/9999.rst.txt new file mode 100644 index 0000000..1b0a992 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.finishers.80.editors.9999 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Form: + formEditor: + propertyCollections: + finishers: + 80: + identifier: SaveToDatabase + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/identifier.rst.txt b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/identifier.rst.txt new file mode 100644 index 0000000..7b26f07 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/propertyCollections/finishers/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.finishers.80.identifier +------------------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.propertyCollections.finishers.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Form: + formEditor: + propertyCollections: + finishers: + 80: + identifier: SaveToDatabase + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageMessage.rst.txt b/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageMessage.rst.txt new file mode 100644 index 0000000..772bdf7 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageMessage.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.saveErrorFlashMessageMessage +--------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.saveErrorFlashMessageMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveErrorFlashMessageMessage: formEditor.elements.Form.saveErrorFlashMessageMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageTitle.rst.txt new file mode 100644 index 0000000..13f96ed --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/saveErrorFlashMessageTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.saveErrorFlashMessageTitle +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.saveErrorFlashMessageTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveErrorFlashMessageTitle: formEditor.elements.Form.saveErrorFlashMessageTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageMessage.rst.txt b/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageMessage.rst.txt new file mode 100644 index 0000000..8973f75 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageMessage.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.saveSuccessFlashMessageMessage +----------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.saveSuccessFlashMessageMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveSuccessFlashMessageMessage: formEditor.elements.Form.saveSuccessFlashMessageMessage + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageTitle.rst.txt b/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageTitle.rst.txt new file mode 100644 index 0000000..7dd43b0 --- /dev/null +++ b/Documentation/I/Config/proto/form/formEditor/saveSuccessFlashMessageTitle.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.saveSuccessFlashMessageTitle +--------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.formEditor.saveSuccessFlashMessageTitle + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Form: + formEditor: + saveSuccessFlashMessageTitle: formEditor.elements.Form.saveSuccessFlashMessageTitle + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Internal setting. diff --git a/Documentation/I/Config/proto/form/renderingOptions/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..666deff --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/_isCompositeFormElement.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions._isCompositeFormElement +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 17 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/form/renderingOptions/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..ed1cff1 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/_isTopLevelFormElement.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions._isTopLevelFormElement +--------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 18 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/form/renderingOptions/addQueryString.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/addQueryString.rst.txt new file mode 100644 index 0000000..81cae91 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/addQueryString.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.addQueryString +------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.addQueryString + +:aspect:`Data type` + bool/string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 11 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Corresponds to the Fluid ``f:form`` ViewHelper option ``addQueryString``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/additionalParams.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/additionalParams.rst.txt new file mode 100644 index 0000000..a4bee38 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/additionalParams.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.additionalParams +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.additionalParams + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 13 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Fluid f:form viewHelper option ``additionalParams``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/argumentsToBeExcludedFromQueryString.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/argumentsToBeExcludedFromQueryString.rst.txt new file mode 100644 index 0000000..a9794e9 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/argumentsToBeExcludedFromQueryString.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.argumentsToBeExcludedFromQueryString +----------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.argumentsToBeExcludedFromQueryString + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 12 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Fluid f:form viewHelper option ``argumentsToBeExcludedFromQueryString``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/controllerAction.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/controllerAction.rst.txt new file mode 100644 index 0000000..b167476 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/controllerAction.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.controllerAction +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.controllerAction + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 14 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +:aspect:`Good to know` + - :ref:`"Render within your own Extbase extension"` + +:aspect:`Description` + Fluid f:form ViewHelper option ``action``. This is useful if you want to render your form within your own extbase extension. diff --git a/Documentation/I/Config/proto/form/renderingOptions/fluidAdditionalAttributes.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/fluidAdditionalAttributes.rst.txt new file mode 100644 index 0000000..be3f1c6 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/fluidAdditionalAttributes.rst.txt @@ -0,0 +1,22 @@ +.. include:: /Includes.rst.txt + +renderingOptions.fluidAdditionalAttributes +------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.fluidAdditionalAttributes + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Good to know` + - :ref:`"Translate form definition"` + +:aspect:`Description` + The values within this array are directly used within the form element ViewHelper's property ``additionalAttributes``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/honeypot/enable.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/honeypot/enable.rst.txt new file mode 100644 index 0000000..88e6b3a --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/honeypot/enable.rst.txt @@ -0,0 +1,90 @@ +.. include:: /Includes.rst.txt +renderingOptions.honeypot.enable +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.honeypot.enable + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 20 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Enable or disable the honeypot feature. + +.. attention:: + + If you want to use a (static) site caching - for example EXT:staticfilecache - + you should disable the automatic inclusion of the honeypot. + + Within your form definition: + + .. code-block:: yaml + + type: Form + identifier: fooForm + label: 'foo' + renderingOptions: + honeypot: + enable: false + renderables: + ... + + Within your form setup: + + .. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + honeypot: + enable: false + + See forge issue `#83212 `_ for more + information. diff --git a/Documentation/I/Config/proto/form/renderingOptions/honeypot/formElementToUse.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/honeypot/formElementToUse.rst.txt new file mode 100644 index 0000000..0f50534 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/honeypot/formElementToUse.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.honeypot.formElementToUse +------------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.honeypot.formElementToUse + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 21 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Define which ```` should be used to render the honeypot. diff --git a/Documentation/I/Config/proto/form/renderingOptions/httpEnctype.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/httpEnctype.rst.txt new file mode 100644 index 0000000..66f7a98 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/httpEnctype.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.httpEnctype +---------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.httpEnctype + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 16 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Fluid f:form viewHelper option ``enctype``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/httpMethod.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/httpMethod.rst.txt new file mode 100644 index 0000000..03f6350 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/httpMethod.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.httpMethod +--------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.httpMethod + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 15 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Fluid f:form viewHelper option ``method``. diff --git a/Documentation/I/Config/proto/form/renderingOptions/layoutRootPaths.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/layoutRootPaths.rst.txt new file mode 100644 index 0000000..c7b8786 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/layoutRootPaths.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.layoutRootPaths +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.layoutRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 9-10 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +:aspect:`Good to know` + - :ref:`"Custom templates"` + +:aspect:`Description` + Please read the section :ref:`layoutRootPaths`. diff --git a/Documentation/I/Config/proto/form/renderingOptions/partialRootPaths.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/partialRootPaths.rst.txt new file mode 100644 index 0000000..9b2a7c8 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/partialRootPaths.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.partialRootPaths +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.partialRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7-8 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +:aspect:`Good to know` + - :ref:`"Custom templates"` + +:aspect:`partialRootPaths` + Please read the section :ref:`templateRootPaths`. diff --git a/Documentation/I/Config/proto/form/renderingOptions/skipUnknownElements.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/skipUnknownElements.rst.txt new file mode 100644 index 0000000..640ce2e --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/skipUnknownElements.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.skipUnknownElements +------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.skipUnknownElements + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 23 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + If set, every unknown ```` will not be rendered. If set to false an exception will be thrown. diff --git a/Documentation/I/Config/proto/form/renderingOptions/submitButtonLabel.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/submitButtonLabel.rst.txt new file mode 100644 index 0000000..7e89b50 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/submitButtonLabel.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.submitButtonLabel +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.submitButtonLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 22 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + The submit Button label. diff --git a/Documentation/I/Config/proto/form/renderingOptions/templateRootPaths.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/templateRootPaths.rst.txt new file mode 100644 index 0000000..2c4275b --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/templateRootPaths.rst.txt @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt +renderingOptions.templateRootPaths +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.templateRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5-6 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +:aspect:`Good to know` + - :ref:`"Custom templates"` + +:aspect:`Description` + Please read the section :ref:`templateRootPaths`. diff --git a/Documentation/I/Config/proto/form/renderingOptions/translation/translationFiles.rst.txt b/Documentation/I/Config/proto/form/renderingOptions/translation/translationFiles.rst.txt new file mode 100644 index 0000000..1dad0d3 --- /dev/null +++ b/Documentation/I/Config/proto/form/renderingOptions/translation/translationFiles.rst.txt @@ -0,0 +1,58 @@ +.. include:: /Includes.rst.txt +renderingOptions.translation.translationFiles +--------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Form.renderingOptions.translation.translationFiles + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Form: + renderingOptions: + translation: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/locallang.xlf' + templateRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Templates/' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Partials/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Frontend/Layouts/' + addQueryString: false + argumentsToBeExcludedFromQueryString: { } + additionalParams: { } + controllerAction: perform + httpMethod: post + httpEnctype: multipart/form-data + _isCompositeFormElement: false + _isTopLevelFormElement: true + honeypot: + enable: true + formElementToUse: Honeypot + submitButtonLabel: Submit + skipUnknownElements: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Filesystem path(s) to translation files which should be searched for form element property translations. + If ``translationFiles`` is undefined, - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Form.renderingOptions.translation.translationFiles" ` will be used. diff --git a/Documentation/I/Config/proto/formEditor/Index.rst b/Documentation/I/Config/proto/formEditor/Index.rst new file mode 100644 index 0000000..a8939eb --- /dev/null +++ b/Documentation/I/Config/proto/formEditor/Index.rst @@ -0,0 +1,710 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formeditor: + +============ +[formEditor] +============ + + +.. _prototypes.prototypeIdentifier.formeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formeditor.translationfiles: + +translationFiles +---------------- + +:aspect:`Option path` + prototypes..formeditor.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + formEditor: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Filesystem path(s) to translation files which should be searched for form editor translations. + + +.. _prototypes.prototypeIdentifier.formeditor.dynamicjavascriptmodules.app: + +dynamicJavaScriptModules.app +---------------------------- + +:aspect:`Option path` + prototypes..formeditor.dynamicJavaScriptModules.app + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + formEditor: + dynamicJavaScriptModules: + app: TYPO3/CMS/Form/Backend/FormEditor + mediator: TYPO3/CMS/Form/Backend/FormEditor/Mediator + viewModel: TYPO3/CMS/Form/Backend/FormEditor/ViewModel + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + ES6 module specifier for the form editor JavaScript app. + + +.. _prototypes.prototypeIdentifier.formeditor.dynamicjavascriptmodules.mediator: + +dynamicJavaScriptModules.mediator +--------------------------------- + +:aspect:`Option path` + prototypes..formeditor.dynamicJavaScriptModules.mediator + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + formEditor: + dynamicJavaScriptModules: + app: TYPO3/CMS/Form/Backend/FormEditor + mediator: TYPO3/CMS/Form/Backend/FormEditor/Mediator + viewModel: TYPO3/CMS/Form/Backend/FormEditor/ViewModel + + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + ES6 module specifier for the form editor JavaScript mediator. + + +.. _prototypes.prototypeIdentifier.formeditor.dynamicjavascriptmodules.viewmodel: + +dynamicJavaScriptModules.viewModel +---------------------------------- + +:aspect:`Option path` + prototypes..formeditor.dynamicJavaScriptModules.viewModel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + formEditor: + dynamicJavaScriptModules: + app: TYPO3/CMS/Form/Backend/FormEditor + mediator: TYPO3/CMS/Form/Backend/FormEditor/Mediator + viewModel: TYPO3/CMS/Form/Backend/FormEditor/ViewModel + + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + ES6 module specifier for the form editor JavaScript view model. + + +.. _prototypes.prototypeIdentifier.formeditor.dynamicjavascriptmodules.additionalviewmodelmodules: + +dynamicJavaScriptModules.additionalViewModelModules +--------------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.dynamicJavaScriptModules.additionalViewModelModules + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (prototype 'standard')` + undefined + +:aspect:`Good to know` + - :ref:`"Form editor"` + - :ref:`"Register custom JavaScript modules"` + +:aspect:`Description` + Array with ES6 module specifiers for custom JavaScript modules. + + +.. _prototypes.prototypeIdentifier.formeditor.addinlinesettings: + +addInlineSettings +----------------- + +:aspect:`Option path` + prototypes..formeditor.addInlineSettings + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (prototype 'standard')` + undefined + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + Adds Javascript Inline Setting. This will occur in TYPO3.settings - object. + + +.. _prototypes.prototypeIdentifier.formeditor.maximumundosteps: + +maximumUndoSteps +---------------- + +:aspect:`Option path` + prototypes..formeditor.maximumUndoSteps + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + formEditor: + maximumUndoSteps: 10 + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + Define the maximum possible undo steps within the form editor. + + +.. _prototypes.prototypeIdentifier.formeditor.stylesheets: + +stylesheets +----------- + +:aspect:`Option path` + prototypes..formeditor.stylesheets + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + formEditor: + stylesheets: + 200: 'EXT:form/Resources/Public/Css/form.css' + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + The CSS files to be used by the ``form editor``. + + +.. _prototypes.prototypeIdentifier.formeditor.formeditorfluidconfiguration: + +formEditorFluidConfiguration +---------------------------- + +:aspect:`Option path` + prototypes..formeditor.formEditorFluidConfiguration + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + formEditor: + formEditorFluidConfiguration: + templatePathAndFilename: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + +:aspect:`Good to know` + - :ref:`"Form editor"` + - :ref:`"view/inspector/editor/insert/perform"` + +:aspect:`Description` + Basic fluid template search path configurations. + + +.. _prototypes.prototypeIdentifier.formeditor.formeditorfluidconfiguration.templatepathandfilename: + +formEditorFluidConfiguration.templatePathAndFilename +---------------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formEditorFluidConfiguration.templatePathAndFilename + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + formEditor: + formEditorFluidConfiguration: + templatePathAndFilename: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + Internal setting. Template which render the inline HTML templates which are used by the form editor JavaScript. + + +.. _prototypes.prototypeIdentifier.formeditor.formeditorfluidconfiguration.partialrootpaths: + +formEditorFluidConfiguration.partialRootPaths +--------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formEditorFluidConfiguration.partialRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4-5 + + formEditor: + formEditorFluidConfiguration: + templatePathAndFilename: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + +:aspect:`Good to know` + - :ref:`"Form editor"` + - :ref:`"view/inspector/editor/insert/perform"` + +:aspect:`Description` + Array with fluid partial search paths for the inline HTML templates which are used by the form editor JavaScript. + + +.. _prototypes.prototypeIdentifier.formeditor.formeditorfluidconfiguration.layoutrootpaths: + +formEditorFluidConfiguration.layoutRootPaths +-------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formEditorFluidConfiguration.layoutRootPaths + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6-7 + + formEditor: + formEditorFluidConfiguration: + templatePathAndFilename: 'EXT:form/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html' + partialRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Partials/FormEditor/' + layoutRootPaths: + 10: 'EXT:form/Resources/Private/Backend/Layouts/FormEditor/' + +:aspect:`Good to know` + - :ref:`"Form editor"` + - :ref:`"view/inspector/editor/insert/perform"` + +:aspect:`Description` + Internal setting. Array with fluid layout search paths. + + +.. _prototypes.prototypeIdentifier.formeditor.formeditorpartials: + +formEditorPartials +------------------ + +:aspect:`Option path` + prototypes..formeditor.formEditorPartials + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + formEditor: + formEditorPartials: + Modal-InsertElements: Modals/InsertElements + Modal-InsertPages: Modals/InsertPages + Modal-ValidationErrors: Modals/ValidationErrors + Inspector-FormElementHeaderEditor: Inspector/FormElementHeaderEditor + Inspector-CollectionElementHeaderEditor: Inspector/CollectionElementHeaderEditor + Inspector-TextEditor: Inspector/TextEditor + Inspector-PropertyGridEditor: Inspector/PropertyGridEditor + Inspector-SingleSelectEditor: Inspector/SingleSelectEditor + Inspector-MultiSelectEditor: Inspector/MultiSelectEditor + Inspector-GridColumnViewPortConfigurationEditor: Inspector/GridColumnViewPortConfigurationEditor + Inspector-TextareaEditor: Inspector/TextareaEditor + Inspector-RemoveElementEditor: Inspector/RemoveElementEditor + Inspector-FinishersEditor: Inspector/FinishersEditor + Inspector-ValidatorsEditor: Inspector/ValidatorsEditor + Inspector-RequiredValidatorEditor: Inspector/RequiredValidatorEditor + Inspector-CheckboxEditor: Inspector/CheckboxEditor + Inspector-ValidationErrorMessageEditor: 'Inspector/ValidationErrorMessageEditor' + Inspector-Typo3WinBrowserEditor: Inspector/Typo3WinBrowserEditor + +:aspect:`Good to know` + - :ref:`"Form editor"` + - :ref:`"Common Abstract view formelement templates"` + - :ref:`"available inspector editors"` + - :ref:`"view/inspector/editor/insert/perform"` + +:aspect:`Description` + Array with mappings for the inline HTML templates. The keys are identifiers which could be used within the JavaScript code. The values are partial paths, relative to :ref:`"prototypes.prototypeIdentifier.formeditor.formEditorFluidConfiguration.partialRootPaths"`. + The partials content will be rendered as inline HTML. This inline HTML templates can be identified and used by such a key (e.g. "Inspector-TextEditor") within the JavaScript code. + + +.. _prototypes.prototypeIdentifier.formeditor.formelementpropertyvalidatorsdefinition: + +formElementPropertyValidatorsDefinition +--------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formElementPropertyValidatorsDefinition + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + formEditor: + formElementPropertyValidatorsDefinition: + NotEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NotEmpty.label + Integer: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.Integer.label + NaiveEmail: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + NaiveEmailOrEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + FormElementIdentifierWithinCurlyBracesInclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FormElementIdentifierWithinCurlyBracesExclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FileSize: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FileSize.label + RFC3339FullDate: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RFC3339FullDate.label + RegularExpressionPattern: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RegularExpressionPattern.label + ItemCount: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.ItemCount.label + IntegerList: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.IntegerList.label + +:aspect:`Related options` + - :ref:`"[TextEditor] propertyValidators"` + - :ref:`"[Typo3WinBrowserEditor] propertyValidators"` + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + Some inspector editors are able to validate it's values through a JavaScript methods. + ``formElementPropertyValidatorsDefinition`` define basic configurations for such JavaScript validators. + This JavaScript validators can be registered through ``getFormEditorApp().addPropertyValidationValidator()``. The first method argument is the identifier + for this validator. Every array key within ``formElementPropertyValidatorsDefinition`` must be equal to such an identifier. + + +.. _prototypes.prototypeIdentifier.formeditor.formelementpropertyvalidatorsdefinition..errormessage: + +formElementPropertyValidatorsDefinition..errorMessage +--------------------------------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formElementPropertyValidatorsDefinition..errorMessage + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4, 6, 8, 10, 12, 14 + + formEditor: + formElementPropertyValidatorsDefinition: + NotEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NotEmpty.label + Integer: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.Integer.label + NaiveEmail: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + NaiveEmailOrEmpty: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.NaiveEmail.label + FormElementIdentifierWithinCurlyBracesInclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FormElementIdentifierWithinCurlyBracesExclusive: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FormElementIdentifierWithinCurlyBraces.label + FileSize: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.FileSize.label + RFC3339FullDate: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RFC3339FullDate.label + RegularExpressionPattern: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.RegularExpressionPattern.label + ItemCount: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.ItemCount.label + IntegerList: + errorMessage: formEditor.formElementPropertyValidatorsDefinition.IntegerList.label + +:aspect:`Related options` + - :ref:`"[TextEditor] propertyValidators"` + - :ref:`"[Typo3WinBrowserEditor] propertyValidators"` + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + The error message for an inspector editor property validator which is shown if the validation fails. + + +.. _prototypes.prototypeIdentifier.formeditor.formelementgroups: + +formElementGroups +----------------- + +:aspect:`Option path` + prototypes..formeditor.formElementGroups + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + formEditor: + formElementGroups: + input: + label: formEditor.formElementGroups.input.label + html5: + label: 'formEditor.formElementGroups.html5.label' + select: + label: formEditor.formElementGroups.select.label + custom: + label: formEditor.formElementGroups.custom.label + container: + label: formEditor.formElementGroups.container.label + page: + label: formEditor.formElementGroups.page.label + +:aspect:`Related options` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.AdvancedPassword.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Checkbox.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.ContentElement.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Date.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Email.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Fieldset.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.FileUpload.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.GridRow.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Hidden.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.ImageUpload.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.MultiCheckbox.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.MultiSelect.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Number.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Page.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Password.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.RadioButton.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.SingleSelect.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.StaticText.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.SummaryPage.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Telephone.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Text.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Textarea.formEditor.group"` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Url.formEditor.group"` + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + Every form element can be placed within a group within the ``form editor`` "new Element" modal. + Every form element which should be shown within such a group, must have a ``group`` property. The form element ``group`` property value + must be equal to an array key within ``formElementGroups``. + + +.. _prototypes.prototypeIdentifier.formeditor.formelementgroups..label: + +formElementGroups..label +---------------------------------------------------- + +:aspect:`Option path` + prototypes..formeditor.formElementGroups..label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4, 6, 8, 10, 12 + + formEditor: + formElementGroups: + input: + label: formEditor.formElementGroups.input.label + select: + label: formEditor.formElementGroups.select.label + custom: + label: formEditor.formElementGroups.custom.label + container: + label: formEditor.formElementGroups.container.label + page: + label: formEditor.formElementGroups.page.label + +:aspect:`Good to know` + - :ref:`"Form editor"` + +:aspect:`Description` + The label for a group within the ``form editor`` "new Element" modal. diff --git a/Documentation/I/Config/proto/formElements/Index.rst b/Documentation/I/Config/proto/formElements/Index.rst new file mode 100644 index 0000000..66239b8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/Index.rst @@ -0,0 +1,828 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition: + +======================== +[formElementsDefinition] +======================== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition-properties.formelementsdefinition: + +[formElementsDefinition] +------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + prototypes: + : + formElementsDefinition: + [...] + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + +:aspect:`Description` + Array which defines the available form elements. Every key within this array is called the ````. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier: + + +--------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition. + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + + prototypes: + standard: + Form: + [...] + Page: + [...] + SummaryPage: + [...] + Fieldset: + [...] + GridRow: + [...] + Text: + [...] + Password: + [...] + AdvancedPassword: + [...] + Textarea: + [...] + Honeypot: + [...] + Hidden: + [...] + Email: + [...] + Telephone: + [...] + Url: + [...] + Number: + [...] + Date: + [...] + Checkbox: + [...] + MultiCheckbox: + [...] + MultiSelect: + [...] + RadioButton: + [...] + SingleSelect: + [...] + StaticText: + [...] + ContentElement: + [...] + FileUpload: + [...] + ImageUpload: + [...] + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + +:aspect:`Description` + This array key identifies a form element. This identifier could be used to attach a form element to a form. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier-commonproperties: + +Common properties +============================================= + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.defaultValue: + +defaultValue +------------ + +:aspect:`Option path` + prototypes..formElementsDefinition..defaultValue + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + undefined + +:aspect:`Description` + If set this string/ array will be used as default value of the form + element. Array is in place for multi value elements (e.g. the + ``MultiSelect`` form element). + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.implementationclassname: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + +:aspect:`Description` + Classname which implements the form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.renderingoptions.translation.translationfiles: + +renderingOptions.translation.translationFiles +--------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..renderingOptions.translation.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Filesystem path(s) to translation files which should be searched for form element property translations. + If ``translationFiles`` is undefined, - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.Form.renderingOptions.translation.translationFiles"` will be used. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.renderingOptions.translation.translatePropertyValueIfEmpty: + +renderingOptions.translation.translatePropertyValueIfEmpty +---------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..renderingoptions.translation.translatepropertyvalueifempty + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + true + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + If set to ``false``, the form element property translation will be skipped if the form element property value is empty. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.renderingoptions.templatename: + +renderingOptions.templateName +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..renderingOptions.templateName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + (see :ref:`concrete element configuration `) + +:aspect:`Default value` + undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"templateName"` + +:aspect:`Description` + Set ``templateName`` to define a custom template name which should be used instead of the ````. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.properties: + +properties +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition..properties + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Array with form element specific properties. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.properties.elementDescription: + +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.properties.fluidadditionalattributes: + +properties.fluidAdditionalAttributes +------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition..properties.fluidAdditionalAttributes + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + The values within this array are directly used within the form element ViewHelper's property ``additionalAttributes``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.properties.gridcolumnclassautoconfiguration: + +properties.gridColumnClassAutoConfiguration +------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..properties.gridColumnClassAutoConfiguration + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Undefined + +:aspect:`Related options` + - :ref:`"GridRow viewPorts"` + +:aspect:`Description` + If the form element lies within a GridRow you can define the number of columns which the form element should occupy. + Each ``viewPorts`` configuration key has to match with on ofe the defined viewports within ``prototypes..formElementsDefinition.GridRow.properties.gridColumnClassAutoConfiguration.viewPorts`` + + .. code-block:: yaml + :linenos: + + gridColumnClassAutoConfiguration: + viewPorts: + lg: + numbersOfColumnsToUse: '2' + md: + numbersOfColumnsToUse: '3' + sm: + numbersOfColumnsToUse: '4' + xs: + numbersOfColumnsToUse: '5' + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.label: + +label +----- + +:aspect:`Option path` + prototypes..formElementsDefinition..label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + The label of the form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor: + +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No (but recommended) + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Array with configurations for the ``form editor`` + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections: + +formEditor.propertyCollections +------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with configurations for ``property collections`` for the form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.validators: + +formEditor.propertyCollections.validators +----------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.validators + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with configurations for available validators for a form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.validators.*.identifier: + +formEditor.propertyCollections.validators.[*].identifier +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.validators.[*].identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.validators.*.editors: + +formEditor.propertyCollections.validators.[*].editors +----------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.validators.[*].editors + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with available ``inspector editors`` for this validator. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.finishers: + +formEditor.propertyCollections.finishers +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.finishers + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with configurations for available finisher for a form definition. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.finishers.*.identifier: + +formEditor.propertyCollections.finishers.[*].identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.finishers.[*].identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the finisher which should be attached to the form definition. Must be equal to an existing ````. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.propertycollections.finishers.*.editors: + +formEditor.propertyCollections.finishers.[*].editors +---------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.propertyCollections.finishers.[*].editors + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with available ``inspector editors`` for this finisher. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.group: + +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formElementGroups ` + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.groupsorting: + +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formEditor.editors-tree: + +formEditor.editors +------------------ + +.. toctree:: + + formEditor/Index + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier-concreteconfigurations: + +Concrete configurations +======================= + +.. toctree:: + + formElementTypes/AdvancedPassword + formElementTypes/Checkbox + formElementTypes/ContentElement + formElementTypes/Date + formElementTypes/Email + formElementTypes/Fieldset + formElementTypes/FileUpload + formElementTypes/GridRow + formElementTypes/Hidden + formElementTypes/Honeypot + formElementTypes/ImageUpload + formElementTypes/MultiCheckbox + formElementTypes/MultiSelect + formElementTypes/Number + formElementTypes/Page + formElementTypes/Password + formElementTypes/RadioButton + formElementTypes/SingleSelect + formElementTypes/StaticText + formElementTypes/SummaryPage + formElementTypes/Telephone + formElementTypes/Text + formElementTypes/Textarea + formElementTypes/Url diff --git a/Documentation/I/Config/proto/formElements/formEditor/Index.rst b/Documentation/I/Config/proto/formElements/formEditor/Index.rst new file mode 100644 index 0000000..40bd317 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/Index.rst @@ -0,0 +1,111 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors: + +================================================== +[][formEditor][editors] +================================================== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors-properties-editors: + +.formEditor.editors +---------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.editors + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Array with numerical keys. Each arrayitem describes an ``inspector editor`` which is used to write values into a form element property. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*-commonproperties: + +Common [][formEditor][editors][*] properties +======================================================================= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier: +.. include:: inspectorEditors/properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename: + +templateName +------------ + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.editors.*.templateName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: inspectorEditors/properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label: +.. include:: inspectorEditors/properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath: +.. include:: inspectorEditors/properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formEditor.editors-availableinspectoreditors: + +available inspector editors +--------------------------- + +.. toctree:: + + inspectorEditors/CheckboxEditor + inspectorEditors/CollectionElementHeaderEditor + inspectorEditors/FinishersEditor + inspectorEditors/FormElementHeaderEditor + inspectorEditors/GridColumnViewPortConfigurationEditor + inspectorEditors/MultiSelectEditor + inspectorEditors/PropertyGridEditor + inspectorEditors/RemoveElementEditor + inspectorEditors/RequiredValidatorEditor + inspectorEditors/SingleSelectEditor + inspectorEditors/TextareaEditor + inspectorEditors/TextEditor + inspectorEditors/Typo3WinBrowserEditor + inspectorEditors/ValidatorsEditor + inspectorEditors/ValidationErrorMessageEditor diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CheckboxEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CheckboxEditor.rst new file mode 100644 index 0000000..3a8a499 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CheckboxEditor.rst @@ -0,0 +1,60 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.checkboxeditor: + +================ +[CheckboxEditor] +================ + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.checkboxeditor-introduction: + +Introduction +============ + +Shows a checkbox which write 'true' or 'false' within the form definition for a form element property. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.checkboxeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-checkboxeditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.\.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-CheckboxEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-checkboxeditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-checkboxeditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-checkboxeditor: +.. include:: properties/PropertyPath.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CollectionElementHeaderEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CollectionElementHeaderEditor.rst new file mode 100644 index 0000000..10e47c6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/CollectionElementHeaderEditor.rst @@ -0,0 +1,57 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.collectionelementheadereditor: + +=============================== +[CollectionElementHeaderEditor] +=============================== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.collectionelementheadereditor-introduction: + +Introduction +============ + +This is not really an editor because this editor don't write values into the form definition. +This editor show the header area for collection elements (finishers/ validators) with it's icon and label. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.collectionelementheadereditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templateName-collectionelementheadereditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.\.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-CollectionElementHeaderEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-collectionelementheadereditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-collectionelementheadereditor: +.. include:: properties/Label.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FinishersEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FinishersEditor.rst new file mode 100644 index 0000000..8954657 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FinishersEditor.rst @@ -0,0 +1,105 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.finisherseditor: + +================= +[FinishersEditor] +================= + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.finisherseditor-introduction: + +Introduction +============ + +Shows a select list with finishers. If a finisher is already added to the form definition, then this finisher will be removed from the select list. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.finisherseditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-finisherseditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-FinishersEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-finisherseditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-finisherseditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.value-finisherseditor: + +selectOptions.[*].value +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`"[finishersDefinition]"` + + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Has to match with a ``prototypes..finishersdefinition`` configuration key. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.label-finisherseditor: + +selectOptions.[*].label +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label which is shown within the select field. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FormElementHeaderEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FormElementHeaderEditor.rst new file mode 100644 index 0000000..915e245 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/FormElementHeaderEditor.rst @@ -0,0 +1,53 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.formelementheadereditor: + +========================= +[FormElementHeaderEditor] +========================= + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.formelementheadereditor-introduction: + +Introduction +============ + +This is not really an editor because this editor don't write values into the form definition. +This editor show the header area for the form element with it's icon and label. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.formelementheadereditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-formelementheadereditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.\.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-FormElementHeaderEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-formelementheadereditor: +.. include:: properties/Identifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/GridColumnViewPortConfigurationEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/GridColumnViewPortConfigurationEditor.rst new file mode 100644 index 0000000..1e05a28 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/GridColumnViewPortConfigurationEditor.rst @@ -0,0 +1,175 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.gridcolumnviewportconfigurationeditor: + +======================================= +[GridColumnViewPortConfigurationEditor] +======================================= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.gridcolumnviewportconfigurationeditor-introduction: + +Introduction +============ + +Shows a viewport selector as buttons and an input field. With this editor, you can define how many columns per viewPort an form element should occupy. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.gridcolumnviewportconfigurationeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templateName-gridcolumnviewportconfigurationeditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.\.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-GridColumnViewPortConfigurationEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-gridcolumnviewportconfigurationeditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-gridcolumnviewportconfigurationeditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.configurationOptions.viewPorts.*.viewPortIdentifier-gridcolumnviewportconfigurationeditor: + +configurationOptions.viewPorts.[*].viewPortIdentifier +----------------------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`"properties.gridColumnClassAutoConfiguration"` + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Has to match with a ``prototypes..formElementsDefinition..properties.gridColumnClassAutoConfiguration.viewPorts`` configuration key. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.configurationOptions.viewPorts.*.label-gridcolumnviewportconfigurationeditor: + +configurationOptions.viewPorts.[*].label +---------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the viewport button. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.configurationOptions.numbersOfColumnsToUse.label-gridcolumnviewportconfigurationeditor: + +configurationOptions.numbersOfColumnsToUse.label +------------------------------------------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the "Numbers of columns" input field. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.configurationOptions.numbersOfColumnsToUse.propertyPath-gridcolumnviewportconfigurationeditor: + +configurationOptions.numbersOfColumnsToUse.propertyPath +------------------------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The path to the property of the form element which should be written. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.configurationOptions.numbersOfColumnsToUse.description-gridcolumnviewportconfigurationeditor: + +configurationOptions.numbersOfColumnsToUse.description +--------------------------------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A text which is shown at the bottom of the "Numbers of columns" input field. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/MultiSelectEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/MultiSelectEditor.rst new file mode 100644 index 0000000..f7d42e5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/MultiSelectEditor.rst @@ -0,0 +1,108 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.multiselecteditor: + +=================== +[MultiSelectEditor] +=================== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.multiselecteditor-introduction: + +Introduction +============ + +Shows a multiselect list with values. If one or more selectoptions are selected, then the option value will be written within a form element property which is defined by the "propertyPath" option. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.multiselecteditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-multiselecteditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-MultiSelectEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-multiselecteditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-multiselecteditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-multiselecteditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.value-multiselecteditor: + +selectOptions.[*].value +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The value which should be written into the corresponding form elements property. + The corresponding form elements property is identified by the ``propertyPath`` option. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.label-multiselecteditor: + +selectOptions.[*].label +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label which is shown within the select field. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/PropertyGridEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/PropertyGridEditor.rst new file mode 100644 index 0000000..ae277a5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/PropertyGridEditor.rst @@ -0,0 +1,207 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertygrideditor: + +==================== +[PropertyGridEditor] +==================== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertygrideditor-introduction: + +Introduction +============ + +Shows a grid which allows you to add (and remove) multiple rows and fill values for each row. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertygrideditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-propertygrideditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-PropertyGridEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-propertygrideditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-propertygrideditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-propertygrideditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.issortable-propertygrideditor: + +isSortable +---------- + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'false' the rows are not sortable. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.enableaddrow-propertygrideditor: + +enableAddRow +------------ + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'false' the "add new row" button is disabled. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.enabledeleterow-propertygrideditor: + +enableDeleteRow +--------------- + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'false' the "delete row" button is disabled. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.multiselection-propertygrideditor: + +multiSelection +-------------- + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'false' only one row can be marked as preselected. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.removelastavailablerowflashmessagetitle-propertygrideditor: + +removeLastAvailableRowFlashMessageTitle +--------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + There must be at least one existing row within this ``inspector editor``. If the last existing row is tried to be removed a flash message is shown. + This property defines the title for the flash message. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.removelastavailablerowflashmessagemessage-propertygrideditor: + +removeLastAvailableRowFlashMessageMessage +----------------------------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + There must be at least one existing row within this ``inspector editor``. If the last existing row is tried to be removed a flash message is shown. + This property defines the text for the flash message. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RemoveElementEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RemoveElementEditor.rst new file mode 100644 index 0000000..acd5a26 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RemoveElementEditor.rst @@ -0,0 +1,52 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.removeelementeditor: + +===================== +[RemoveElementEditor] +===================== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.removeelementeditor-introduction: + +Introduction +============ + +This editor show a button which allows you to remove the form element or the collection element (finishers/ validators). + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.removeelementeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-removeelementeditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-RemoveElementEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-removeelementeditor: +.. include:: properties/Identifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RequiredValidatorEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RequiredValidatorEditor.rst new file mode 100644 index 0000000..1b4b9f3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/RequiredValidatorEditor.rst @@ -0,0 +1,127 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.requiredvalidatoreditor: + +========================= +[RequiredValidatorEditor] +========================= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.requiredvalidatoreditor-introduction: + +Introduction +============ + +Shows a checkbox. If set, a validator ('NotEmpty' by default) will be written into the ``form definition``. In addition another property could be written into the ``form definition``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.requiredvalidatoreditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-requiredvalidatoreditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-RequiredValidatorEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-requiredvalidatoreditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-requiredvalidatoreditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validatoridentifier-requiredvalidatoreditor: + +validatorIdentifier +------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + The ```` which should be used. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-requiredvalidatoreditor: + +propertyPath +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + An property path which should be written into the `form definition`` if the checkbox is set. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertyvalue-requiredvalidatoreditor: + +propertyValue +------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + The value for the property path which should be written into the `form definition`` if the checkbox is set. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/SingleSelectEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/SingleSelectEditor.rst new file mode 100644 index 0000000..acfbe47 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/SingleSelectEditor.rst @@ -0,0 +1,110 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.singleselecteditor: + +==================== +[SingleSelectEditor] +==================== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.singleselecteditor-introduction: + +Introduction +============ + +Shows a single select list with values. If a selectoption is selected, then the option value will be written within a form element property which is defined by the "propertyPath" option. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.singleselecteditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-singleselecteditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-SingleSelectEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-singleselecteditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-singleselecteditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-singleselecteditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.value-singleselecteditor: + +selectOptions.[*].value +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The value which should be written into the corresponding form elements property. + The corresponding form elements property is identified by the ``propertyPath`` option. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.label-singleselecteditor: + +selectOptions.[*].label +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label which is shown within the select field. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextEditor.rst new file mode 100644 index 0000000..3a66cf1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextEditor.rst @@ -0,0 +1,205 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.texteditor: + +============ +[TextEditor] +============ + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.texteditor-introduction: + +Introduction +============ + +Shows a single line textfield. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.texteditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-texteditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-TextEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-texteditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-texteditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-texteditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.donotsetifpropertyvalueisempty-texteditor: + +doNotSetIfPropertyValueIsEmpty +------------------------------ + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to true then the property which should be written through this ``inspector editor`` will be removed within the ``form definition`` if the + value from the ``inspector editor`` is empty instead of writing an empty value ('') for this property. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertyvalidators-texteditor: + +propertyValidators +------------------ + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Related options` + - :ref:`"formElementPropertyValidatorsDefinition"` + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + This ``inspector editors`` is able to validate it's value through JavaScript methods. + This JavaScript validators can be registered through ``getFormEditorApp().addPropertyValidationValidator()``. + The first method argument is the identifier for such a validator. + Every array value within ``propertyValidators`` must be equal to such an identifier. + + For example: + + .. code-block:: yaml + + propertyValidators: + 10: 'Integer' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertyvalidatorsmode-texteditor: + +propertyValidatorsMode +---------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value` + AND + +:aspect:`possible values` + OR/ AND + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'OR' then at least one validator must be valid to accept the ``inspector editor`` value. If set to 'AND' then all validators must be valid. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.description-texteditor: + +description +-------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + A text which is shown at the bottom of the ``inspector editor``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.additionalelementpropertypaths-texteditor: + +additionalElementPropertyPaths +------------------------------ + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + An array which holds property paths which should be written in addition to the propertyPath option. + + For example: + + .. code-block:: yaml + + additionalElementPropertyPaths: + 10: 'properties.fluidAdditionalAttributes.maxlength' diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextareaEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextareaEditor.rst new file mode 100644 index 0000000..c221cf6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/TextareaEditor.rst @@ -0,0 +1,158 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.textareaeditor: + +================ +[TextareaEditor] +================ + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.textareaeditor-introduction: + +Introduction +============ + +Shows a textarea. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.textareaeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-textareaeditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-TextareaEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-textareaeditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-textareaeditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-textareaeditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.enablerichtext-textareaeditor: + +enableRichtext +-------------- + +:aspect:`Data type` + boolean + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + false + +:aspect:`Description` + If set to true, the textarea will be rendered as a rich text editor using CKEditor 5. + This allows for formatted text input with features like bold, italic, links, and lists. + + The RTE configuration is loaded from the global TYPO3 RTE presets defined in the + system configuration. Use the ``richtextConfiguration`` option to specify which + preset should be used. + +.. :aspect:`Example` + .. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + StaticText: + formEditor: + editors: + 100: + identifier: text + templateName: Inspector-TextareaEditor + label: formEditor.elements.StaticText.editor.text.label + propertyPath: text + enableRichtext: true + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.richtextconfiguration-textareaeditor: + +richtextConfiguration +--------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + 'form-label' + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.enablerichtext-textareaeditor` + +:aspect:`Description` + Defines which RTE preset configuration should be used when ``enableRichtext`` is true. + The preset name must correspond to a preset defined in the global TYPO3 RTE configuration. + + Common preset names include: + + - ``form-label`` - Simple formatting for labels and short texts (bold, italic, link) - default + - ``form-content`` - Extended formatting for content fields (includes lists) + - ``default`` - The default TYPO3 RTE configuration + - ``minimal`` - A minimal configuration with basic formatting + - ``full`` - A full-featured configuration with all available features + + If the specified preset does not exist, the system will fall back to the 'form-label' preset. + +.. :aspect:`Example` + .. code-block:: yaml + + prototypes: + standard: + formElementsDefinition: + Form: + formEditor: + propertyCollections: + finishers: + 50: + identifier: Confirmation + editors: + 300: + identifier: message + templateName: Inspector-TextareaEditor + label: formEditor.elements.Form.finisher.Confirmation.editor.message.label + propertyPath: options.message + enableRichtext: true + richtextConfiguration: form-label + diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/Typo3WinBrowserEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/Typo3WinBrowserEditor.rst new file mode 100644 index 0000000..b0cb2a7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/Typo3WinBrowserEditor.rst @@ -0,0 +1,278 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.typo3winbrowsereditor: + +======================= +[Typo3WinBrowserEditor] +======================= + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.typo3winbrowsereditor-introduction: + +Introduction +============ + +Shows a popup window to select records (e.g. pages or tt_content records) as you know it from within the form engine. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.typo3winbrowsereditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-typo3winbrowsereditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-Typo3WinBrowserEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-typo3winbrowsereditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-typo3winbrowsereditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-typo3winbrowsereditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.buttonlabel-typo3winbrowsereditor: + +buttonLabel +----------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + The label for the button which opens the popup window. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.browsabletype-typo3winbrowsereditor: + +browsableType +------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + The allowed selectable record types e.g 'pages' or 'tt_content'. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.iconidentifier-typo3winbrowsereditor: + +iconIdentifier +-------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + The icon to use for the button which triggers the record browser. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertyvalidators-typo3winbrowsereditor: + +propertyValidators +------------------ + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Related options` + - :ref:`"formElementPropertyValidatorsDefinition"` + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + This ``inspector editors`` is able to validate it's value through JavaScript methods. + This JavaScript validators can be registered through ``getFormEditorApp().addPropertyValidationValidator()``. + The first method argument is the identifier for such a validator. + Every array value within ``propertyValidators`` must be equal to such an identifier. + + For example: + + .. code-block:: yaml + + propertyValidators: + 10: 'IntegerList' + 20: 'FormElementIdentifierWithinCurlyBracesExclusive' + + When :ref:`minItems` + or :ref:`maxItems` + is configured, the ``ItemCount`` validator is added automatically and does + not need to be listed in ``propertyValidators``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertyvalidatorsmode-typo3winbrowsereditor: + +propertyValidatorsMode +---------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value` + AND + +:aspect:`possible values` + OR/ AND + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + If set to 'OR' then at least one validator must be valid to accept the ``inspector editor`` value. If set to 'AND' then all validators must be valid. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.description-typo3winbrowsereditor: + +description +-------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + A text which is shown at the bottom of the ``inspector editor``. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.maxItems-typo3winbrowsereditor: + +maxItems +-------------- + +:aspect:`Data type` + integer + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Maximum number of records. Defaults to 1. When set, the number of selected + records is validated automatically through the ``ItemCount`` validator. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.minItems-typo3winbrowsereditor: + +minItems +-------------- + +:aspect:`Data type` + integer + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Minimum number of records. Defaults to 0. When set, the number of selected + records is validated automatically through the ``ItemCount`` validator. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidationErrorMessageEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidationErrorMessageEditor.rst new file mode 100644 index 0000000..0ec0c7e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidationErrorMessageEditor.rst @@ -0,0 +1,84 @@ +.. include:: /Includes.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validationerrormessageeditor: + +============================== +[ValidationErrorMessageEditor] +============================== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validationerrormessageeditor-introduction: + +Introduction +============ + +Shows a textarea. It allows the definition of custom validation error messages. Within the form editor, one can set +those error messages for all existing validators. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validationerrormessageeditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-validationerrormessageeditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-ValidationErrorMessageEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-validationerrormessageeditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-validationerrormessageeditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.propertypath-validationerrormessageeditor: +.. include:: properties/PropertyPath.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.description-validationerrormessageeditor: + +description +-------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +.. :aspect:`Related options` + @ToDo + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + A text which is shown at the bottom of the ``inspector editor``. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidatorsEditor.rst b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidatorsEditor.rst new file mode 100644 index 0000000..fb2e2ce --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/ValidatorsEditor.rst @@ -0,0 +1,104 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validatorseditor: + +================== +[ValidatorsEditor] +================== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validatorseditor-introduction: + +Introduction +============ + +Shows a select list with validators. If a validator is already added to the form element, then this validator will be removed from the select list. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.validatorseditor-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.templatename-validatorseditor: + +templateName +------------ + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`prototypes.prototypeIdentifier.formEditor.formEditorPartials ` + +:aspect:`value` + Inspector-FinishersEditor + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + .. include:: properties/TemplateName.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.identifier-validatorseditor: +.. include:: properties/Identifier.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.label-validatorseditor: +.. include:: properties/Label.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.value-validatorseditor: + +selectOptions.[*].value +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Related options` + - :ref:`"[validatorsDefinition]"` + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Has to match with a ``prototypes..validatorsDefinition`` configuration key. + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.formelementtypeidentifier.formeditor.editors.*.selectoptions.*.label-validatorseditor: + +selectOptions.[*].label +----------------------- + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +.. :aspect:`Related options` + @ToDo + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label which is shown within the select field. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Identifier.rst.txt b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Identifier.rst.txt new file mode 100644 index 0000000..2d69d5e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Identifier.rst.txt @@ -0,0 +1,25 @@ + +identifier +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.editors.*.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + +:aspect:`Description` + Identifies the current ``inspector editor`` within the current form element. + The identifier is a text of your choice but must be unique within the optionpath ``prototypes.prototypeIdentifier.formElementsDefinition.formelementtypeidentifier.formEditor.editors``. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Label.rst.txt b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Label.rst.txt new file mode 100644 index 0000000..68f95b9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/Label.rst.txt @@ -0,0 +1,25 @@ + +label +----- + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.editors.*.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + The label for this ``inspector editor`` which is shown within the ``inspector component``. diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/PropertyPath.rst.txt b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/PropertyPath.rst.txt new file mode 100644 index 0000000..f219ebf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/PropertyPath.rst.txt @@ -0,0 +1,26 @@ + +propertyPath +------------ + +:aspect:`Option path` + prototypes..formElementsDefinition..formEditor.editors.*.propertyPath + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"JavaScript FormElement model"` + +:aspect:`Description` + The path to the property of the form element which should be written by this ``inspector editor``. + diff --git a/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/TemplateName.rst.txt b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/TemplateName.rst.txt new file mode 100644 index 0000000..2d97fe7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formEditor/inspectorEditors/properties/TemplateName.rst.txt @@ -0,0 +1,4 @@ + + +The inline HTML template which is used for this inspector editor. +Must be equal to an existing array key within ``prototypes..formEditor.formEditorPartials`` and must be started with 'Inspector-' by convention. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword.rst b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword.rst new file mode 100644 index 0000000..c2f45d4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword.rst @@ -0,0 +1,190 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword: + +================== +[AdvancedPassword] +================== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.implementationclassname: +.. include:: AdvancedPassword/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.containerclassattribute: +.. include:: AdvancedPassword/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.elementclassattribute: +.. include:: AdvancedPassword/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.elementDescription: +.. include:: AdvancedPassword/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.elementerrorclassattribute: +.. include:: AdvancedPassword/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.confirmationlabel: +.. include:: AdvancedPassword/properties/confirmationLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.properties.confirmationclassattribute: +.. include:: AdvancedPassword/properties/confirmationClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor: +.. include:: AdvancedPassword/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.100: +.. include:: AdvancedPassword/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.200: +.. include:: AdvancedPassword/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.230: +.. include:: AdvancedPassword/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.300: +.. include:: AdvancedPassword/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.400: +.. include:: AdvancedPassword/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.700: +.. include:: AdvancedPassword/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.800: +.. include:: AdvancedPassword/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.900: +.. include:: AdvancedPassword/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.editors.9999: +.. include:: AdvancedPassword/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.predefineddefaults: +.. include:: AdvancedPassword/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.10: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.10.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.10.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.10.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.20: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.20.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.20.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.20.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30.editors.200: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30.editors.300: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.30.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.40: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.40.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.40.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.40.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.50: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.50.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.50.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.50.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.60: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.60.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.60.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.60.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70.editors.200: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70.editors.300: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.70.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.80: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.80.identifier: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.80.editors.100: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.80.editors.200: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.propertycollections.validators.80.editors.9999: +.. include:: AdvancedPassword/formEditor/propertyCollections/validators/80/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.label: +.. include:: AdvancedPassword/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.group: +.. include:: AdvancedPassword/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.groupsorting: +.. include:: AdvancedPassword/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.advancedpassword.formeditor.iconidentifier: +.. include:: AdvancedPassword/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor.rst.txt new file mode 100644 index 0000000..193a896 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor.rst.txt @@ -0,0 +1,241 @@ + +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + AdvancedPassword: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 300: + identifier: confirmationLabel + templateName: Inspector-TextEditor + label: formEditor.elements.AdvancedPassword.editor.confirmationLabel.label + propertyPath: properties.confirmationLabel + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + confirmationLabel: formEditor.element.AdvancedPassword.editor.confirmationLabel.predefinedDefaults + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.AdvancedPassword.label + group: custom + groupSorting: 500 + iconIdentifier: form-advanced-password diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..c0efeba --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ + + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..dbf1fdd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..5cae377 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ + +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..e4ae44f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 300: + identifier: confirmationLabel + templateName: Inspector-TextEditor + label: formEditor.elements.AdvancedPassword.editor.confirmationLabel.label + propertyPath: properties.confirmationLabel diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..27121c3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/400.rst.txt @@ -0,0 +1,35 @@ + + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..7635cca --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/700.rst.txt @@ -0,0 +1,49 @@ + +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..dc9b8be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ + + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..0d3ca00 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/900.rst.txt @@ -0,0 +1,54 @@ + + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..d9902b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/editors/9999.rst.txt @@ -0,0 +1,31 @@ + + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + AdvancedPassword: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/group.rst.txt new file mode 100644 index 0000000..d651cf3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/group.rst.txt @@ -0,0 +1,31 @@ + +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + AdvancedPassword: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..9223436 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ + +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + AdvancedPassword: + formEditor: + groupSorting: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..9fc3f72 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + AdvancedPassword: + formEditor: + iconIdentifier: form-advanced-password + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/label.rst.txt new file mode 100644 index 0000000..4556865 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/label.rst.txt @@ -0,0 +1,30 @@ + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + AdvancedPassword: + formEditor: + label: formEditor.elements.AdvancedPassword.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..1021ae1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + AdvancedPassword: + formEditor: + predefinedDefaults: + properties: + confirmationLabel: formEditor.element.AdvancedPassword.editor.confirmationLabel.predefinedDefaults + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..c476d14 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,36 @@ + + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..d9b7d9c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..fac9f0b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..552fa3e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20.rst.txt new file mode 100644 index 0000000..fb4d63e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20.rst.txt @@ -0,0 +1,36 @@ + + +formEditor.propertyCollections.validators.20 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/100.rst.txt new file mode 100644 index 0000000..9baa68b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.20.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/9999.rst.txt new file mode 100644 index 0000000..04872be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.20.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/identifier.rst.txt new file mode 100644 index 0000000..3e68505 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/20/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.20.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30.rst.txt new file mode 100644 index 0000000..5e14e8a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30.rst.txt @@ -0,0 +1,54 @@ + + +formEditor.propertyCollections.validators.30 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/100.rst.txt new file mode 100644 index 0000000..6a322f1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.30.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/200.rst.txt new file mode 100644 index 0000000..cfd4121 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/200.rst.txt @@ -0,0 +1,38 @@ + + +formEditor.propertyCollections.validators.30.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/300.rst.txt new file mode 100644 index 0000000..5d87845 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/300.rst.txt @@ -0,0 +1,38 @@ + + +formEditor.propertyCollections.validators.30.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/9999.rst.txt new file mode 100644 index 0000000..b2816f8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.30.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/identifier.rst.txt new file mode 100644 index 0000000..2bb529b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/30/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.30.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..2d6c477 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,36 @@ + + +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..5627a6a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/9999.rst.txt new file mode 100644 index 0000000..fb52af7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.40.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..ca5d3cf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50.rst.txt new file mode 100644 index 0000000..13d04c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50.rst.txt @@ -0,0 +1,36 @@ + + +formEditor.propertyCollections.validators.50 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/100.rst.txt new file mode 100644 index 0000000..86dc3a7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.50.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/9999.rst.txt new file mode 100644 index 0000000..a10dd54 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.50.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/identifier.rst.txt new file mode 100644 index 0000000..e9e8727 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/50/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.50.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..6de4730 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,36 @@ + + +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..3c757db --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/9999.rst.txt new file mode 100644 index 0000000..c02b7c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.60.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..13721b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..4db55a1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,54 @@ + + +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..0ae15e0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..5effaea --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ + + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..68fe775 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ + + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..1e65c52 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..bc7fc89 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..0e83bbd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,45 @@ + + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..c67ff09 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,33 @@ + + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..66135b3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,38 @@ + + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/9999.rst.txt new file mode 100644 index 0000000..1907b0e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/editors/9999.rst.txt @@ -0,0 +1,32 @@ + + +formEditor.propertyCollections.validators.80.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..c359123 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ + +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/implementationClassName.rst.txt new file mode 100644 index 0000000..c5c25d4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/implementationClassName.rst.txt @@ -0,0 +1,35 @@ + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + AdvancedPassword: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\AdvancedPassword + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationClassAttribute.rst.txt new file mode 100644 index 0000000..00b085e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationClassAttribute.rst.txt @@ -0,0 +1,40 @@ + +properties.confirmationClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.confirmationClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7 + + AdvancedPassword: + properties: + containerClassAttribute: input + elementClassAttribute: input-medium + elementErrorClassAttribute: error + confirmationLabel: '' + confirmationClassAttribute: input-medium + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the password confirmation form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationLabel.rst.txt new file mode 100644 index 0000000..7e9966f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/confirmationLabel.rst.txt @@ -0,0 +1,40 @@ + +properties.confirmationLabel +---------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.confirmationLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + AdvancedPassword: + properties: + containerClassAttribute: input + elementClassAttribute: input-medium + elementErrorClassAttribute: error + confirmationLabel: '' + confirmationClassAttribute: input-medium + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the password confirmation form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..1ee8fbd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/containerClassAttribute.rst.txt @@ -0,0 +1,40 @@ + +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + AdvancedPassword: + properties: + containerClassAttribute: input + elementClassAttribute: input-medium + elementErrorClassAttribute: error + confirmationLabel: '' + confirmationClassAttribute: input-medium + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..b9f6d01 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementClassAttribute.rst.txt @@ -0,0 +1,40 @@ + +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + AdvancedPassword: + properties: + containerClassAttribute: input + elementClassAttribute: input-medium + elementErrorClassAttribute: error + confirmationLabel: '' + confirmationClassAttribute: input-medium + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementDescription.rst.txt new file mode 100644 index 0000000..2b649ce --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ + +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..df58b1a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/AdvancedPassword/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,40 @@ + +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.AdvancedPassword.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + AdvancedPassword: + properties: + containerClassAttribute: input + elementClassAttribute: input-medium + elementErrorClassAttribute: error + confirmationLabel: '' + confirmationClassAttribute: input-medium + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox.rst new file mode 100644 index 0000000..d19fdf0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox.rst @@ -0,0 +1,68 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox: + +========== +[Checkbox] +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.implementationclassname: +.. include:: Checkbox/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.properties.containerclassattribute: +.. include:: Checkbox/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.properties.elementclassattribute: +.. include:: Checkbox/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.properties.elementDescription: +.. include:: Checkbox/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.properties.elementerrorclassattribute: +.. include:: Checkbox/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.properties.value: +.. include:: Checkbox/properties/value.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor: +.. include:: Checkbox/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.100: +.. include:: Checkbox/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.200: +.. include:: Checkbox/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.230: +.. include:: Checkbox/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.700: +.. include:: Checkbox/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.800: +.. include:: Checkbox/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.editors.9999: +.. include:: Checkbox/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.predefineddefaults: +.. include:: Checkbox/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.label: +.. include:: Checkbox/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.group: +.. include:: Checkbox/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.groupsorting: +.. include:: Checkbox/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.checkbox.formeditor.iconidentifier: +.. include:: Checkbox/formEditor/iconIdentifier.rst.txt + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor.rst.txt new file mode 100644 index 0000000..aa8c1f9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor.rst.txt @@ -0,0 +1,74 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Checkbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: { } + label: formEditor.elements.Checkbox.label + group: select + groupSorting: 100 + iconIdentifier: form-checkbox diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..4e87005 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Checkbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..aef4a31 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Checkbox: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..55db3d6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..38f5d2e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Checkbox: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..d0b30be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Checkbox: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..f588ed4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Checkbox: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/group.rst.txt new file mode 100644 index 0000000..99d48a0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + formEditor: + group: select + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..3eb28b1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..d1ff1b5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + formEditor: + iconIdentifier: form-checkbox + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/label.rst.txt new file mode 100644 index 0000000..5753a88 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + formEditor: + label: formEditor.elements.Checkbox.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..4975859 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + formEditor: + predefinedDefaults: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/implementationClassName.rst.txt new file mode 100644 index 0000000..4d2807e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Checkbox: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..55de358 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/containerClassAttribute.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Checkbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: add-on + elementErrorClassAttribute: error + value: 1 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..2552753 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementClassAttribute.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Checkbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: add-on + elementErrorClassAttribute: error + value: 1 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementDescription.rst.txt new file mode 100644 index 0000000..6dab5c8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..c218598 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Checkbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: add-on + elementErrorClassAttribute: error + value: 1 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/value.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/value.rst.txt new file mode 100644 index 0000000..557ad42 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Checkbox/properties/value.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +properties.value +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Checkbox.properties.value + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Checkbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: add-on + elementErrorClassAttribute: error + value: 1 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The value of the checkbox which should be sent to the server. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement.rst b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement.rst new file mode 100644 index 0000000..b7e1efb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement.rst @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement: + +================ +[ContentElement] +================ + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.implementationclassname: +.. include:: ContentElement/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.properties.contentelementuid: +.. include:: ContentElement/properties/contentElementUid.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor: +.. include:: ContentElement/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.editors.100: +.. include:: ContentElement/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.editors.300: +.. include:: ContentElement/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.editors.700: +.. include:: ContentElement/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.editors.9999: +.. include:: ContentElement/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.predefineddefaults: +.. include:: ContentElement/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.label: +.. include:: ContentElement/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.group: +.. include:: ContentElement/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.groupsorting: +.. include:: ContentElement/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.contentelement.formeditor.iconidentifier: +.. include:: ContentElement/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor.rst.txt new file mode 100644 index 0000000..ae0271c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor.rst.txt @@ -0,0 +1,70 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + ContentElement: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 300: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.ContentElement.editor.contentElement.label + buttonLabel: formEditor.elements.ContentElement.editor.contentElement.buttonLabel + browsableType: tt_content + propertyPath: properties.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + contentElementUid: '' + label: formEditor.elements.ContentElement.label + group: custom + groupSorting: 700 + iconIdentifier: form-content-element diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..172c7f8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ContentElement: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..ab6d24d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[Typo3WinBrowserEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ContentElement: + formEditor: + editors: + 300: + identifier: contentElement + templateName: Inspector-Typo3WinBrowserEditor + label: formEditor.elements.ContentElement.editor.contentElement.label + buttonLabel: formEditor.elements.ContentElement.editor.contentElement.buttonLabel + browsableType: tt_content + propertyPath: properties.contentElementUid + propertyValidatorsMode: OR + propertyValidators: + 10: Integer + 20: FormElementIdentifierWithinCurlyBracesExclusive diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..e4522ec --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ContentElement: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..c961839 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ContentElement: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/group.rst.txt new file mode 100644 index 0000000..4c29173 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ContentElement: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..c5b3720 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ContentElement: + formEditor: + groupSorting: 700 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..adee9bd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ContentElement: + formEditor: + iconIdentifier: form-content-element + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/label.rst.txt new file mode 100644 index 0000000..5b3975e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ContentElement: + formEditor: + label: formEditor.elements.ContentElement.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..c051dda --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + ContentElement: + formEditor: + predefinedDefaults: + properties: + contentElementUid: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/implementationClassName.rst.txt new file mode 100644 index 0000000..5d46903 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + ContentElement: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/properties/contentElementUid.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/properties/contentElementUid.rst.txt new file mode 100644 index 0000000..f2c1471 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ContentElement/properties/contentElementUid.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +properties.contentElementUid +---------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ContentElement.properties.contentElementUid + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ContentElement: + properties: + contentElementUid: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The uid of the content element which should be rendered. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Date.rst new file mode 100644 index 0000000..0de1dd3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date.rst @@ -0,0 +1,236 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date: + +============ +[Date] +============ + +The form framework contains a form element called 'Date' which is technically an HTML5 'date' form element. + +The ``DateRange`` validator is the server side validation equivalent to the client side validation through the ``min`` +and ``max`` HTML attribute and should always be used in combination. If the ``DateRange`` validator is added to the +form element within the form editor, the ``min`` and ``max`` HTML attributes are added automatically. + +Browsers which do not support the HTML5 date element gracefully degrade to a text input. The HTML5 date element always +normalizes the value to the format Y-m-d (RFC 3339 'full-date'). With a text input, by default the browser has no +recognition of which format the date should be in. A workaround could be to put a pattern attribute on the date input. +Even though the date input does not use it, the text input fallback will. + +By default, the HTML attribute ``pattern="([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])"`` is rendered on the +date form element. Note that this basic regular expression does not support leap years and does not check for the +correct number of days in a month. But as a start, this should be sufficient. The same pattern is used by the form +editor to validate the properties ``defaultValue`` and the ``DateRange`` validator options ``minimum`` and ``maximum``. + +Read more: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#Handling_browser_support + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.implementationclassname: +.. include:: Date/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.properties.containerclassattribute: +.. include:: Date/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.properties.displayFormat: +.. include:: Date/properties/displayFormat.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.properties.elementclassattribute: +.. include:: Date/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.properties.elementerrorclassattribute: +.. include:: Date/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.properties.fluidAdditionalAttributes.pattern: +.. include:: Date/properties/fluidAdditionalAttributes/pattern.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor: +.. include:: Date/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.100: +.. include:: Date/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.200: +.. include:: Date/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.230: +.. include:: Date/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.500: +.. include:: Date/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.550: +.. include:: Date/formEditor/editors/550.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.700: +.. include:: Date/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.800: +.. include:: Date/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.900: +.. include:: Date/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.editors.9999: +.. include:: Date/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.predefineddefaults: +.. include:: Date/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10: +.. include:: Date/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.identifier: +.. include:: Date/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.editors.250: +.. include:: Date/formEditor/propertyCollections/validators/10/editors/250.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.editors.300: +.. include:: Date/formEditor/propertyCollections/validators/10/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.10.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.20: +.. include:: Date/formEditor/propertyCollections/validators/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.20.identifier: +.. include:: Date/formEditor/propertyCollections/validators/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.20.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.20.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/20/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.20.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30: +.. include:: Date/formEditor/propertyCollections/validators/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.identifier: +.. include:: Date/formEditor/propertyCollections/validators/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.editors.300: +.. include:: Date/formEditor/propertyCollections/validators/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.editors.400: +.. include:: Date/formEditor/propertyCollections/validators/30/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.30.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.40: +.. include:: Date/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.40.identifier: +.. include:: Date/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.40.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.40.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/40/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.40.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.50: +.. include:: Date/formEditor/propertyCollections/validators/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.50.identifier: +.. include:: Date/formEditor/propertyCollections/validators/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.50.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.50.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/50/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.50.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.60: +.. include:: Date/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.60.identifier: +.. include:: Date/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.60.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.60.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/60/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.60.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70: +.. include:: Date/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.identifier: +.. include:: Date/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.editors.300: +.. include:: Date/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.editors.400: +.. include:: Date/formEditor/propertyCollections/validators/70/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.70.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80: +.. include:: Date/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80.identifier: +.. include:: Date/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80.editors.100: +.. include:: Date/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80.editors.200: +.. include:: Date/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80.editors.300: +.. include:: Date/formEditor/propertyCollections/validators/80/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.propertycollections.validators.80.editors.9999: +.. include:: Date/formEditor/propertyCollections/validators/80/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.label: +.. include:: Date/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.group: +.. include:: Date/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.groupsorting: +.. include:: Date/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.date.formeditor.iconidentifier: +.. include:: Date/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor.rst.txt new file mode 100644 index 0000000..31eeff8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor.rst.txt @@ -0,0 +1,119 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + DatePicker: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + placeholder: formEditor.elements.Date.editor.defaultValue.placeholder + propertyValidators: + 10: RFC3339FullDateOrEmpty + 550: + identifier: 'step' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Date.editor.step.label' + description: 'formEditor.elements.Date.editor.step.description' + propertyPath: 'properties.fluidAdditionalAttributes.step' + propertyValidators: + 10: 'Integer' + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: DateRange + label: formEditor.elements.Date.editor.validators.DateRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: + properties: + fluidAdditionalAttributes: + min: + max: + step: 1 + propertyCollections: + ... + label: formEditor.elements.Date.label + group: html5 + groupSorting: 500 + iconIdentifier: form-date-picker diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..efe3b46 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..3104a2c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..9fe009b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..7fb7bb1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/500.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + placeholder: formEditor.elements.Date.editor.defaultValue.placeholder + propertyValidators: + 10: RFC3339FullDateOrEmpty diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/550.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/550.rst.txt new file mode 100644 index 0000000..a9f8e2d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/550.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.550 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.550 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 550: + identifier: step + templateName: Inspector-TextEditor + label: formEditor.elements.Date.editor.step.label + description: formEditor.elements.Date.editor.step.description + propertyPath: properties.fluidAdditionalAttributes.step + propertyValidators: + 10: integer diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..cf3916c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..2f2a6db --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/800.rst.txt @@ -0,0 +1,44 @@ +.. include:: /Includes.rst.txt +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..a627c27 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/900.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.DatePicker.editor.validators.EmptyValue.label + 20: + value: DateTime + label: formEditor.elements.DatePicker.editor.validators.DateRange.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..b3cdb8e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/group.rst.txt new file mode 100644 index 0000000..4348842 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Date: + formEditor: + group: html5 + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..f46b9f5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Date: + formEditor: + groupSorting: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..c7fa43d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Date: + formEditor: + iconIdentifier: form-date-picker + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the ``\TYPO3\CMS\Core\Imaging\IconRegistry``. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/label.rst.txt new file mode 100644 index 0000000..3892959 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Date: + formEditor: + label: formEditor.elements.Date.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..ff656f1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Date: + formEditor: + predefinedDefaults: + defaultValue: + properties: + fluidAdditionalAttributes: + min: + max: + step: 1 + +:aspect:`Good to know` + The properties ``defaultValue``, ``properties.fluidAdditionalAttributes.min``, + ``properties.fluidAdditionalAttributes.max`` must have the format 'Y-m-d' which represents the RFC 3339 + 'full-date' format. + + Read more: https://www.w3.org/TR/2011/WD-html-markup-20110405/input.date.html + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..f27f273 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,66 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.header.label + 200 + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1521293685 + 20: 1521293686 + 30: 1521293687 + propertyPath: properties.validationErrorMessages + 250: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.minimum + placeholder: formEditor.elements.DatePicker.validators.DateRange.editor.minimum.placeholder + propertyPath: options.minimum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.maximum + placeholder: formEditor.elements.DatePicker.validators.DateRange.editor.maximum.placeholder + propertyPath: options.maximum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..0645a36 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/200.rst.txt new file mode 100644 index 0000000..9877100 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.editors.200 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Alphanumeric.editor.validationErrorMessage.description + errorCodes: + 10: 1521293685 + 20: 1521293686 + 30: 1521293687 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/250.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/250.rst.txt new file mode 100644 index 0000000..685a102 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/250.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.250 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.editors.250 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 250: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.minimum + placeholder: formEditor.elements.DatePicker.validators.DateRange.editor.minimum.placeholder + propertyPath: options.minimum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/300.rst.txt new file mode 100644 index 0000000..d5865d4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.DatePicker.validators.DateRange.editor.maximum + placeholder: formEditor.elements.DatePicker.validators.DateRange.editor.maximum.placeholder + propertyPath: options.maximum + propertyValidators: + 10: RFC3339FullDateOrEmpty + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..57e66b3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..baf4968 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 10: + identifier: DateRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20.rst.txt new file mode 100644 index 0000000..71a0592 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/100.rst.txt new file mode 100644 index 0000000..b409839 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/200.rst.txt new file mode 100644 index 0000000..e2b9acd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.20.editors.200 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Text.editor.validationErrorMessage.description + errorCodes: + 10: 1221565786 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/9999.rst.txt new file mode 100644 index 0000000..6716f82 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/identifier.rst.txt new file mode 100644 index 0000000..0f7ed2d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/20/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30.rst.txt new file mode 100644 index 0000000..95b66ef --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30.rst.txt @@ -0,0 +1,65 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/100.rst.txt new file mode 100644 index 0000000..0e7ff37 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/200.rst.txt new file mode 100644 index 0000000..9f877e3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/300.rst.txt new file mode 100644 index 0000000..dc87ee4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/400.rst.txt new file mode 100644 index 0000000..3b973dc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/400.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30.editors.400 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.editors.400 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.StringLength.editor.validationErrorMessage.description + errorCodes: + 10: 1238110957 + 20: 1269883975 + 30: 1428504122 + 40: 1238108068 + 50: 1238108069 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/9999.rst.txt new file mode 100644 index 0000000..b82145a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/identifier.rst.txt new file mode 100644 index 0000000..80223d1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/30/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..c6204b0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..e5e5d63 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/200.rst.txt new file mode 100644 index 0000000..2a0927c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.40.editors.200 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.EmailAddress.editor.validationErrorMessage.description + errorCodes: + 10: 1221559976 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/9999.rst.txt new file mode 100644 index 0000000..1be0499 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..0666619 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50.rst.txt new file mode 100644 index 0000000..d903d94 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/100.rst.txt new file mode 100644 index 0000000..b1742f9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/200.rst.txt new file mode 100644 index 0000000..466d07b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.50.editors.200 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Integer.editor.validationErrorMessage.description + errorCodes: + 10: 1221560494 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/9999.rst.txt new file mode 100644 index 0000000..437b330 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/identifier.rst.txt new file mode 100644 index 0000000..d1effaf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/50/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..6e1314f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..4041903 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/200.rst.txt new file mode 100644 index 0000000..4320628 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.60.editors.200 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 200: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.Float.editor.validationErrorMessage.description + errorCodes: + 10: 1221560288 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/9999.rst.txt new file mode 100644 index 0000000..3d404f9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..8364859 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..3832a2b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,62 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..cdc966f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..c97a7e3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..b527123 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/400.rst.txt new file mode 100644 index 0000000..593df9c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.editors.400 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.editors.400 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 400: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.NumberRange.editor.validationErrorMessage.description + errorCodes: + 10: 1221563685 + 20: 1221561046 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..45a4195 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..f776a25 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..70b32fe --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,52 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..706683a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..7c905e1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/300.rst.txt new file mode 100644 index 0000000..814339e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/300.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80.editors.300 + +:aspect:`Data type` + array/ :ref:`[ValidationErrorMessageEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 300: + identifier: validationErrorMessage + templateName: Inspector-ValidationErrorMessageEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.validationErrorMessage.description + errorCodes: + 10: 1221565130 + propertyPath: properties.validationErrorMessages diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/9999.rst.txt new file mode 100644 index 0000000..c83885d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..c669441 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/implementationClassName.rst.txt new file mode 100644 index 0000000..98e0609 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Date: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..5e001fe --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/containerClassAttribute.rst.txt @@ -0,0 +1,41 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Date: + properties: + containerClassAttribute: input + elementClassAttribute: + elementErrorClassAttribute: error + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/displayFormat.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/displayFormat.rst.txt new file mode 100644 index 0000000..9b75fb6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/displayFormat.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.displayFormat +------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.properties.displayFormat + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Date: + properties: + containerClassAttribute: input + elementClassAttribute: + elementErrorClassAttribute: error + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The display format defines the display format of the submitted value within the + summary step, email finishers etc. but **not** for the form element value itself. + The display format of the form element value depends on the browser settings and + can not be defined! + + Read more: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date#Value diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..780d5dc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementClassAttribute.rst.txt @@ -0,0 +1,41 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Date: + properties: + containerClassAttribute: input + elementClassAttribute: + elementErrorClassAttribute: error + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..83620e6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,41 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Date: + properties: + containerClassAttribute: input + elementClassAttribute: + elementErrorClassAttribute: error + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/fluidAdditionalAttributes/pattern.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/fluidAdditionalAttributes/pattern.rst.txt new file mode 100644 index 0000000..d4bb5de --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Date/properties/fluidAdditionalAttributes/pattern.rst.txt @@ -0,0 +1,41 @@ +.. include:: /Includes.rst.txt +properties.fluidAdditionalAttributes.pattern +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Date.properties.fluidAdditionalAttributes.pattern + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8 + + Date: + properties: + containerClassAttribute: input + elementClassAttribute: + elementErrorClassAttribute: error + displayFormat: d.m.Y + fluidAdditionalAttributes: + pattern: '([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Pattern to be matched by the form control's value. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Email.rst new file mode 100644 index 0000000..b4dbb37 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email.rst @@ -0,0 +1,85 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email: + +======= +[Email] +======= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.implementationclassname: +.. include:: Email/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.properties.containerclassattribute: +.. include:: Email/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.properties.elementclassattribute: +.. include:: Email/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.properties.elementDescription: +.. include:: Email/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.properties.elementerrorclassattribute: +.. include:: Email/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.validators: +.. include:: Email/validators.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor: +.. include:: Email/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.100: +.. include:: Email/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.200: +.. include:: Email/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.230: +.. include:: Email/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.400: +.. include:: Email/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.500: +.. include:: Email/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.700: +.. include:: Email/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.800: +.. include:: Email/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.900: +.. include:: Email/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.editors.9999: +.. include:: Email/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.predefineddefaults: +.. include:: Email/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.propertycollections.validators.40: +.. include:: Email/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.propertycollections.validators.40.identifier: +.. include:: Email/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.propertycollections.validators.40.editors.100: +.. include:: Email/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.label: +.. include:: Email/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.group: +.. include:: Email/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.groupsorting: +.. include:: Email/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.email.formeditor.iconidentifier: +.. include:: Email/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor.rst.txt new file mode 100644 index 0000000..a06aa5e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor.rst.txt @@ -0,0 +1,111 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Email: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + propertyValidators: + 10: NaiveEmailOrEmpty + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + validators: + - + identifier: EmailAddress + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + label: formEditor.elements.Email.label + group: html5 + groupSorting: 100 + iconIdentifier: form-email diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..1c6136f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/100.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..9cb07bc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..55c45a5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..2f3be99 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..93b1bd4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..e7e91c3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/700.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..97d494b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..7d71d07 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/900.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..fa057c9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Email: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/group.rst.txt new file mode 100644 index 0000000..476bce9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/group.rst.txt @@ -0,0 +1,28 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Email: + formEditor: + group: html5 + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..a6b2bf5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Email: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..f6b4e40 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Email: + formEditor: + iconIdentifier: form-email + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/label.rst.txt new file mode 100644 index 0000000..576f7bc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Email: + formEditor: + label: formEditor.elements.Email.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..91f6acf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Email: + formEditor: + predefinedDefaults: + defaultValue: '' + validators: + - + identifier: EmailAddress + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..cd79df1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Email: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..ff9d840 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Email: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..1bd9d43 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Email: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/implementationClassName.rst.txt new file mode 100644 index 0000000..06ede1e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Email: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..8a6643c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Email: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..3168d28 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Email: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementDescription.rst.txt new file mode 100644 index 0000000..516de3f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..ea1d504 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Email: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Email/validators.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Email/validators.rst.txt new file mode 100644 index 0000000..d7d8c4c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Email/validators.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +validators +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Email.validators + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Email: + validators: + - + identifier: EmailAddress + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Predefined validators. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset.rst new file mode 100644 index 0000000..a8567f1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset.rst @@ -0,0 +1,58 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset: + +========== +[Fieldset] +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.implementationclassname: +.. include:: Fieldset/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.properties.elementclassattribute: +.. include:: Fieldset/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.properties.elementerrorclassattribute: +.. include:: Fieldset/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.renderingoptions._iscompositeformelement: +.. include:: Fieldset/renderingOptions/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor: +.. include:: Fieldset/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.editors.100: +.. include:: Fieldset/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.editors.200: +.. include:: Fieldset/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.editors.700: +.. include:: Fieldset/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.editors.9999: +.. include:: Fieldset/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.predefineddefaults: +.. include:: Fieldset/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.label: +.. include:: Fieldset/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.group: +.. include:: Fieldset/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.groupsorting: +.. include:: Fieldset/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor.iconidentifier: +.. include:: Fieldset/formEditor/iconIdentifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fieldset.formeditor._iscompositeformelement: +.. include:: Fieldset/formEditor/_isCompositeFormElement.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor.rst.txt new file mode 100644 index 0000000..4a5788c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor.rst.txt @@ -0,0 +1,63 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Fieldset: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Fieldset.editor.label.label + propertyPath: label + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: { } + label: formEditor.elements.Fieldset.label + group: container + groupSorting: 100 + _isCompositeFormElement: true + iconIdentifier: form-fieldset diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..a915a54 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/_isCompositeFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isCompositeFormElement +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + _isCompositeFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..cf61f66 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Fieldset: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..e8a6e86 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Fieldset: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Fieldset.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..f3799ab --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Fieldset: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..3602628 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Fieldset: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/group.rst.txt new file mode 100644 index 0000000..7bfc551 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + group: container + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..4706f95 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..0fab81b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + iconIdentifier: form-fieldset + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/label.rst.txt new file mode 100644 index 0000000..368d04d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + label: formEditor.elements.Fieldset.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..1ce5f9e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Fieldset: + formEditor: + predefinedDefaults: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/implementationClassName.rst.txt new file mode 100644 index 0000000..61d45b8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Fieldset: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Section + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..19e84a3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Fieldset: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..8a9fb0a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Fieldset: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/renderingOptions/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/renderingOptions/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..34e8f80 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Fieldset/renderingOptions/_isCompositeFormElement.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +renderingOptions._isCompositeFormElement +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Fieldset.renderingOptions._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + AdvancedPassword: + renderingOptions: + _isCompositeFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload.rst b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload.rst new file mode 100644 index 0000000..f3af492 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload.rst @@ -0,0 +1,97 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload: + +============ +[FileUpload] +============ + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.implementationclassname: +.. include:: FileUpload/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.containerclassattribute: +.. include:: FileUpload/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.elementclassattribute: +.. include:: FileUpload/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.elementDescription: +.. include:: FileUpload/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.elementerrorclassattribute: +.. include:: FileUpload/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.savetofilemount: +.. include:: FileUpload/properties/saveToFileMount.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.properties.allowedmimetypes: +.. include:: FileUpload/properties/allowedMimeTypes.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor: +.. include:: FileUpload/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.100: +.. include:: FileUpload/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.200: +.. include:: FileUpload/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.230: +.. include:: FileUpload/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.300: +.. include:: FileUpload/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.400: +.. include:: FileUpload/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.700: +.. include:: FileUpload/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.800: +.. include:: FileUpload/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.900: +.. include:: FileUpload/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.editors.9999: +.. include:: FileUpload/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.predefineddefaults: +.. include:: FileUpload/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10: +.. include:: FileUpload/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10.identifier: +.. include:: FileUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10.editors.100: +.. include:: FileUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10.editors.200: +.. include:: FileUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10.editors.300: +.. include:: FileUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.propertycollections.validators.10.editors.9999: +.. include:: FileUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.label: +.. include:: FileUpload/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.group: +.. include:: FileUpload/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.groupsorting: +.. include:: FileUpload/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.fileupload.formeditor.iconidentifier: +.. include:: FileUpload/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor.rst.txt new file mode 100644 index 0000000..5c33d06 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor.rst.txt @@ -0,0 +1,151 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + FileUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: application/msword + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.doc + 20: + value: application/vnd.openxmlformats-officedocument.wordprocessingml.document + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.docx + 30: + value: application/msexcel + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xls + 40: + value: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xlsx + 50: + value: application/pdf + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.pdf + 60: + value: application/vnd.oasis.opendocument.text + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.odt + 70: + value: application/vnd.oasis.opendocument.spreadsheet-template + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.ods + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: 'validators' + templateName: 'Inspector-ValidatorsEditor' + label: 'formEditor.elements.FileUploadMixin.editor.validators.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label' + 20: + value: 'FileSize' + label: 'formEditor.elements.FileUploadMixin.editor.validators.FileSize.label' + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/pdf + label: formEditor.elements.FileUpload.label + group: custom + groupSorting: 100 + iconIdentifier: form-file-upload diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..2296aef --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..ea52182 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..93827c3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..096e600 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/300.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[MultiSelectEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: application/msword + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.doc + 20: + value: application/vnd.openxmlformats-officedocument.wordprocessingml.document + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.docx + 30: + value: application/msexcel + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xls + 40: + value: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.xlsx + 50: + value: application/pdf + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.pdf + 60: + value: application/vnd.oasis.opendocument.text + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.odt + 70: + value: application/vnd.oasis.opendocument.spreadsheet-template + label: formEditor.elements.FileUpload.editor.allowedMimeTypes.ods diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..7a08b00 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[SingleSelectEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..a279e95 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/700.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..d244960 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..78c022e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/900.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.FileUploadMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label + 20: + value: FileSize + label: formEditor.elements.FileUploadMixin.editor.validators.FileSize.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..f2c88c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/editors/9999.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + FileUpload: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/group.rst.txt new file mode 100644 index 0000000..f654959 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileUpload: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..e4b0ca5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileUpload: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..e845a1d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileUpload: + formEditor: + iconIdentifier: form-file-upload + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/label.rst.txt new file mode 100644 index 0000000..7104ac3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileUpload: + formEditor: + label: formEditor.elements.FileUpload.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..359cec2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + FileUpload: + formEditor: + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..a48c6d9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..8ec514d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt new file mode 100644 index 0000000..b35df44 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt new file mode 100644 index 0000000..38ac5db --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..9321f1f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..09e5cf6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + FileUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/implementationClassName.rst.txt new file mode 100644 index 0000000..0c90d4d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + FileUpload: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/allowedMimeTypes.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/allowedMimeTypes.rst.txt new file mode 100644 index 0000000..4f5b97e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/allowedMimeTypes.rst.txt @@ -0,0 +1,44 @@ +.. include:: /Includes.rst.txt +properties.allowedMimeTypes +--------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.allowedMimeTypes + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7- + + FileUpload: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/msword + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.oasis.opendocument.text + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The allowed mime types for the file uploads. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..b473e61 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/containerClassAttribute.rst.txt @@ -0,0 +1,44 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileUpload: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/msword + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.oasis.opendocument.text + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..cd73c5b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementClassAttribute.rst.txt @@ -0,0 +1,44 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + FileUpload: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/msword + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.oasis.opendocument.text + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementDescription.rst.txt new file mode 100644 index 0000000..6764231 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..68cedb4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,44 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + FileUpload: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/msword + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.oasis.opendocument.text + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/saveToFileMount.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/saveToFileMount.rst.txt new file mode 100644 index 0000000..178114f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/FileUpload/properties/saveToFileMount.rst.txt @@ -0,0 +1,48 @@ +.. include:: /Includes.rst.txt +properties.saveToFileMount +-------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.FileUpload.properties.saveToFileMount + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + FileUpload: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - application/msword + - application/vnd.openxmlformats-officedocument.wordprocessingml.document + - application/vnd.oasis.opendocument.text + - application/pdf + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The location (file mount) for the uploaded files. + If this file mount or the property "saveToFileMount" does not exist + the folder in which the form definition lies (persistence identifier) will be used. + If the form is generated programmatically and therefore no persistence identifier exist + the default storage "1:/user_upload/" will be used. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow.rst b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow.rst new file mode 100644 index 0000000..3f55583 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow.rst @@ -0,0 +1,76 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow: + +========= +[GridRow] +========= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.implementationclassname: +.. include:: GridRow/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.containerclassattribute: +.. include:: GridRow/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.elementclassattribute: +.. include:: GridRow/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.elementerrorclassattribute: +.. include:: GridRow/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.gridcolumnclassautoconfiguration.gridsize: +.. include:: GridRow/properties/gridColumnClassAutoConfiguration/gridSize.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.gridcolumnclassautoconfiguration.viewports: +.. include:: GridRow/properties/gridColumnClassAutoConfiguration/viewPorts.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.properties.gridcolumnclassautoconfiguration.viewports.*.classpattern: +.. include:: GridRow/properties/gridColumnClassAutoConfiguration/viewPorts/classPattern.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.renderingoptions._iscompositeformelement: +.. include:: GridRow/renderingOptions/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.renderingoptions._isgridrowformelement: +.. include:: GridRow/renderingOptions/_isGridRowFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor: +.. include:: GridRow/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.editors.100: +.. include:: GridRow/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.editors.200: +.. include:: GridRow/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.editors.700: +.. include:: GridRow/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.editors.9999: +.. include:: GridRow/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.predefineddefaults: +.. include:: GridRow/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor._iscompositeformelement: +.. include:: GridRow/formEditor/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor._isgridrowformelement: +.. include:: GridRow/formEditor/_isGridRowFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.label: +.. include:: GridRow/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.group: +.. include:: GridRow/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.groupsorting: +.. include:: GridRow/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.gridrow.formeditor.iconidentifier: +.. include:: GridRow/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor.rst.txt new file mode 100644 index 0000000..4934188 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor.rst.txt @@ -0,0 +1,64 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + GridRow: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.GridRow.editor.label.label + propertyPath: label + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: { } + label: formEditor.elements.GridRow.label + group: container + groupSorting: 300 + _isCompositeFormElement: true + _isGridRowFormElement: true + iconIdentifier: form-gridrow diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..bd7069b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isCompositeFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isCompositeFormElement +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + _isCompositeFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isGridRowFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isGridRowFormElement.rst.txt new file mode 100644 index 0000000..bdb1256 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/_isGridRowFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isGridRowFormElement +-------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor._isGridRowFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + _isGridRowFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + todo diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..099d858 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + GridRow: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..5491815 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + GridRow: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.GridRow.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..caa397a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + GridRow: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..4b5b0ae --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + GridRow: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/group.rst.txt new file mode 100644 index 0000000..8e1d641 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + group: container + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..a0f4784 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + groupSorting: 300 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..c7ebdf7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + iconIdentifier: form-gridrow + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/label.rst.txt new file mode 100644 index 0000000..fbda95d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + formEditor: + label: formEditor.elements.GridRow.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..3369ed1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + GridRow: + formEditor: + predefinedDefaults: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/implementationClassName.rst.txt new file mode 100644 index 0000000..c06b4df --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + GridRow: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GridRow + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..71375b3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/containerClassAttribute.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..7acfdcb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementClassAttribute.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..d2fce2f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/gridSize.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/gridSize.rst.txt new file mode 100644 index 0000000..5ba53fc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/gridSize.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +properties.gridColumnClassAutoConfiguration.gridSize +---------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.gridColumnClassAutoConfiguration.gridSize + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7 + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The grid size of the CSS grid system (bootstrap by default). diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts.rst.txt new file mode 100644 index 0000000..6d7b99c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +properties.gridColumnClassAutoConfiguration.viewPorts +----------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.gridColumnClassAutoConfiguration.viewPorts + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +:aspect:`Related options` + - :ref:`"properties.gridColumnClassAutoConfiguration"` + +:aspect:`Description` + Each configuration key within `properties.gridColumnClassAutoConfiguration.viewPorts` represents an viewport of the CSS grid system (bootstrap by default). diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts/classPattern.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts/classPattern.rst.txt new file mode 100644 index 0000000..f16bf1e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/properties/gridColumnClassAutoConfiguration/viewPorts/classPattern.rst.txt @@ -0,0 +1,53 @@ +.. include:: /Includes.rst.txt +properties.gridColumnClassAutoConfiguration.viewPorts.[*].classPattern +---------------------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.properties.gridColumnClassAutoConfiguration.viewPorts..classPattern + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 10, 12, 14, 16 + + GridRow: + properties: + containerClassAttribute: input + elementClassAttribute: row + elementErrorClassAttribute: error + gridColumnClassAutoConfiguration: + gridSize: 12 + viewPorts: + xs: + classPattern: 'col-{@numbersOfColumnsToUse}' + sm: + classPattern: 'col-sm-{@numbersOfColumnsToUse}' + md: + classPattern: 'col-md-{@numbersOfColumnsToUse}' + lg: + classPattern: 'col-lg-{@numbersOfColumnsToUse}' + +:aspect:`Related options` + - :ref:`"properties.gridColumnClassAutoConfiguration"` + +:aspect:`Description` + Defines the CSS class pattern for the CSS grid system. + Each viewport `classPattern` will be wrapped around a form element within a grid row. + The `{@numbersOfColumnsToUse}` placeholder will be replaced by the number of columns which the respective form element should occupy. + The number of columns which the respective form element should occupy has to defined within the respective form elements within a GridRow. + If a form element has no number of columns defined, the ``{@numbersOfColumnsToUse}`` are calculated automatically. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..ec3be60 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isCompositeFormElement.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +renderingOptions._isCompositeFormElement +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.renderingOptions._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + GridRow: + renderingOptions: + _isCompositeFormElement: true + _isGridRowFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isGridRowFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isGridRowFormElement.rst.txt new file mode 100644 index 0000000..ceae6e9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/GridRow/renderingOptions/_isGridRowFormElement.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +renderingOptions._isGridRowFormElement +-------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.GridRow.renderingOptions._isGridRowFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + GridRow: + renderingOptions: + _isCompositeFormElement: true + _isGridRowFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden.rst new file mode 100644 index 0000000..ffa1099 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden.rst @@ -0,0 +1,59 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden: + +======== +[Hidden] +======== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.implementationclassname: +.. include:: Hidden/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.properties.containerclassattribute: +.. include:: Hidden/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.properties.elementclassattribute: +.. include:: Hidden/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.properties.elementerrorclassattribute: +.. include:: Hidden/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor: +.. include:: Hidden/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.editors.100: +.. include:: Hidden/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.editors.200: +.. include:: Hidden/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.editors.300: +.. include:: Hidden/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.editors.700: +.. include:: Hidden/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.editors.9999: +.. include:: Hidden/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.predefineddefaults: +.. include:: Hidden/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.label: +.. include:: Hidden/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.group: +.. include:: Hidden/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.groupsorting: +.. include:: Hidden/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.hidden.formeditor.iconidentifier: +.. include:: Hidden/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor.rst.txt new file mode 100644 index 0000000..2594dcd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor.rst.txt @@ -0,0 +1,68 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Hidden: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 300: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.Hidden.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + label: formEditor.elements.Hidden.label + group: custom + groupSorting: 300 + iconIdentifier: form-hidden diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..7db2fe5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Hidden: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..266c1dc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Hidden: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..4e022c6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Hidden: + formEditor: + editors: + 300: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.Hidden.editor.defaultValue.label + propertyPath: defaultValue diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..ffe570e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Hidden: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..84f87fe --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Hidden: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/group.rst.txt new file mode 100644 index 0000000..64bd3b3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Hidden: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..85d17f6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Hidden: + formEditor: + groupSorting: 300 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..a0b5f55 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Hidden: + formEditor: + iconIdentifier: form-hidden + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/label.rst.txt new file mode 100644 index 0000000..c2edf2b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Hidden: + formEditor: + label: formEditor.elements.Hidden.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..68fe787 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Hidden: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/implementationClassName.rst.txt new file mode 100644 index 0000000..ee14127 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Hidden: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..79b7ddb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Hidden: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..7ea7a46 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Hidden: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..eaa6bcd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Hidden/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Hidden.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Hidden: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot.rst new file mode 100644 index 0000000..465902f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot.rst @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot: + +========== +[Honeypot] +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.implementationclassname: +.. include:: Honeypot/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.properties.containerclassattribute: +.. include:: Honeypot/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.properties.elementclassattribute: +.. include:: Honeypot/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.properties.elementerrorclassattribute: +.. include:: Honeypot/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.properties.renderashiddenfield: +.. include:: Honeypot/properties/renderAsHiddenField.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.honeypot.properties.styleattribute: +.. include:: Honeypot/properties/styleAttribute.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/implementationClassName.rst.txt new file mode 100644 index 0000000..08c6945 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Honeypot: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..66a74a7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/containerClassAttribute.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Honeypot: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..37d2875 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementClassAttribute.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Honeypot: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..a1a2acd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Honeypot: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/renderAsHiddenField.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/renderAsHiddenField.rst.txt new file mode 100644 index 0000000..54692f8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/renderAsHiddenField.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +properties.renderAsHiddenField +------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.properties.renderAsHiddenField + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Honeypot: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + By default the honeypot will be rendered as a regular text form element (input type "text"). ``renderAsHiddenField`` renders the honeypot as a hidden form element (input type "hidden"). diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/styleAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/styleAttribute.rst.txt new file mode 100644 index 0000000..c633d00 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Honeypot/properties/styleAttribute.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt +properties.styleAttribute +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Honeypot.properties.styleAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7 + + Honeypot: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + renderAsHiddenField: false + styleAttribute: 'position:absolute; margin:0 0 0 -999em;' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + By default the honeypot will be rendered as a regular text form element (input type "text"). The ``styleAttribute`` is written to the honeypot form element to make it "invisible" for humans. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload.rst b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload.rst new file mode 100644 index 0000000..b915df3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload.rst @@ -0,0 +1,106 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload: + +============= +[ImageUpload] +============= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.implementationclassname: +.. include:: ImageUpload/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.containerclassattribute: +.. include:: ImageUpload/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.elementclassattribute: +.. include:: ImageUpload/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.elementDescription: +.. include:: ImageUpload/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.elementerrorclassattribute: +.. include:: ImageUpload/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.savetofilemount: +.. include:: ImageUpload/properties/saveToFileMount.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.allowedmimetypes: +.. include:: ImageUpload/properties/allowedMimeTypes.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.imagelinkmaxwidth: +.. include:: ImageUpload/properties/imageLinkMaxWidth.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.imagemaxwidth: +.. include:: ImageUpload/properties/imageMaxWidth.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.properties.imagemaxheight: +.. include:: ImageUpload/properties/imageMaxHeight.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor: +.. include:: ImageUpload/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.100: +.. include:: ImageUpload/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.200: +.. include:: ImageUpload/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.230: +.. include:: ImageUpload/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.300: +.. include:: ImageUpload/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.400: +.. include:: ImageUpload/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.700: +.. include:: ImageUpload/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.800: +.. include:: ImageUpload/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.900: +.. include:: ImageUpload/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.editors.9999: +.. include:: ImageUpload/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.predefineddefaults: +.. include:: ImageUpload/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10.identifier: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10.editors.100: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10.editors.200: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10.editors.300: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.propertycollections.validators.10.editors.9999: +.. include:: ImageUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.label: +.. include:: ImageUpload/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.group: +.. include:: ImageUpload/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.groupsorting: +.. include:: ImageUpload/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.imageupload.formeditor.iconidentifier: +.. include:: ImageUpload/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor.rst.txt new file mode 100644 index 0000000..9f35f61 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor.rst.txt @@ -0,0 +1,139 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + ImageUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: image/jpeg + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.jpg + 20: + value: image/png + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.png + 30: + value: image/bmp + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.bmp + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: 'validators' + templateName: 'Inspector-ValidatorsEditor' + label: 'formEditor.elements.FileUploadMixin.editor.validators.label' + selectOptions: + 10: + value: '' + label: 'formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label' + 20: + value: 'FileSize' + label: 'formEditor.elements.FileUploadMixin.editor.validators.FileSize.label' + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + label: formEditor.elements.ImageUpload.label + group: custom + groupSorting: 400 + iconIdentifier: form-image-upload diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..255efdb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..1e1887f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..16bcaa1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.230 + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..32796a2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/300.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 300: + identifier: allowedMimeTypes + templateName: Inspector-MultiSelectEditor + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.label + propertyPath: properties.allowedMimeTypes + selectOptions: + 10: + value: image/jpeg + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.jpg + 20: + value: image/png + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.png + 30: + value: image/bmp + label: formEditor.elements.ImageUpload.editor.allowedMimeTypes.bmp diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..c6b05ad --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/400.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[SingleSelectEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 400: + identifier: saveToFileMount + templateName: Inspector-SingleSelectEditor + label: formEditor.elements.FileUploadMixin.editor.saveToFileMount.label + propertyPath: properties.saveToFileMount + selectOptions: + 10: + value: '1:/user_upload/' + label: '1:/user_upload/' + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..517666d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..a13ce5b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..e8f97b4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/900.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.FileUploadMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.FileUploadMixin.editor.validators.EmptyValue.label + 20: + value: FileSize + label: formEditor.elements.FileUploadMixin.editor.validators.FileSize.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..822dc3e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + ImageUpload: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/group.rst.txt new file mode 100644 index 0000000..ea8dd9c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ImageUpload: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..5456e8d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ImageUpload: + formEditor: + groupSorting: 400 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..90c57ea --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ImageUpload: + formEditor: + iconIdentifier: form-image-upload + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/label.rst.txt new file mode 100644 index 0000000..11de493 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ImageUpload: + formEditor: + label: formEditor.elements.ImageUpload.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..7ea7afd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + ImageUpload: + formEditor: + predefinedDefaults: + properties: + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..f6cd1af --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..7bfb433 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt new file mode 100644 index 0000000..5fc9abd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/200.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: FileSize diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt new file mode 100644 index 0000000..1598ce8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/300.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: FileSize diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..8670d67 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..aef94fd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + ImageUpload: + formEditor: + propertyCollections: + validators: + 10: + identifier: FileSize + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/implementationClassName.rst.txt new file mode 100644 index 0000000..3be183d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + ImageUpload: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\FileUpload + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/allowedMimeTypes.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/allowedMimeTypes.rst.txt new file mode 100644 index 0000000..ffc3c14 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/allowedMimeTypes.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.allowedMimeTypes +--------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.allowedMimeTypes + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 7-10 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The allowed mime types for the image uploads. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..17b937d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/containerClassAttribute.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..72aa9c8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementClassAttribute.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementDescription.rst.txt new file mode 100644 index 0000000..79d1b86 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..1fe2d18 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageLinkMaxWidth.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageLinkMaxWidth.rst.txt new file mode 100644 index 0000000..b9b9797 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageLinkMaxWidth.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.imageLinkMaxWidth +---------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.imageLinkMaxWidth + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 11 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The max width for the uploaded image preview link. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxHeight.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxHeight.rst.txt new file mode 100644 index 0000000..c8d2a5d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxHeight.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.imageMaxHeight +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.imageMaxHeight + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 13 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The max height for the uploaded image preview. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxWidth.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxWidth.rst.txt new file mode 100644 index 0000000..1ab22cf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/imageMaxWidth.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt +properties.imageMaxWidth +------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.imageMaxWidth + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 12 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The max width for the uploaded image preview. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/saveToFileMount.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/saveToFileMount.rst.txt new file mode 100644 index 0000000..4b5ed54 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/ImageUpload/properties/saveToFileMount.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +properties.saveToFileMount +-------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.ImageUpload.properties.saveToFileMount + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + ImageUpload: + properties: + containerClassAttribute: input + elementClassAttribute: lightbox + elementErrorClassAttribute: error + saveToFileMount: '1:/user_upload/' + allowedMimeTypes: + - image/jpeg + - image/png + - image/bmp + imageLinkMaxWidth: 500 + imageMaxWidth: 500 + imageMaxHeight: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The location (file mount) for the uploaded images. + If this file mount or the property "saveToFileMount" does not exist + the folder in which the form definition lies (persistence identifier) will be used. + If the form is generated programmatically and therefore no persistence identifier exist + the default storage "1:/user_upload/" will be used. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox.rst b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox.rst new file mode 100644 index 0000000..2bf46be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox.rst @@ -0,0 +1,88 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox: + +=============== +[MultiCheckbox] +=============== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.implementationclassname: +.. include:: MultiCheckbox/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.properties.containerclassattribute: +.. include:: MultiCheckbox/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.properties.elementclassattribute: +.. include:: MultiCheckbox/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.properties.elementDescription: +.. include:: MultiCheckbox/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.properties.elementerrorclassattribute: +.. include:: MultiCheckbox/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor: +.. include:: MultiCheckbox/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.100: +.. include:: MultiCheckbox/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.200: +.. include:: MultiCheckbox/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.230: +.. include:: MultiCheckbox/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.300: +.. include:: MultiCheckbox/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.700: +.. include:: MultiCheckbox/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.800: +.. include:: MultiCheckbox/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.900: +.. include:: MultiCheckbox/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.editors.9999: +.. include:: MultiCheckbox/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.predefineddefaults: +.. include:: MultiCheckbox/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10.identifier: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10.editors.100: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10.editors.200: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10.editors.300: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.propertycollections.validators.10.editors.9999: +.. include:: MultiCheckbox/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.label: +.. include:: MultiCheckbox/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.group: +.. include:: MultiCheckbox/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.groupsorting: +.. include:: MultiCheckbox/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multicheckbox.formeditor.iconidentifier: +.. include:: MultiCheckbox/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor.rst.txt new file mode 100644 index 0000000..dd5c507 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor.rst.txt @@ -0,0 +1,122 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + MultiCheckbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.MultiCheckbox.label + group: select + groupSorting: 400 + iconIdentifier: form-multi-checkbox diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..2ec405b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..8349e51 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..2e39857 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..0501655 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..7e38913 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..e6df211 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..27fb532 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/900.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..7a4f3c4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiCheckbox: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/group.rst.txt new file mode 100644 index 0000000..7a068ea --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiCheckbox: + formEditor: + group: select + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..79d9d50 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiCheckbox: + formEditor: + groupSorting: 400 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..ab92ee3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiCheckbox: + formEditor: + iconIdentifier: form-multi-checkbox + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/label.rst.txt new file mode 100644 index 0000000..1d14898 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiCheckbox: + formEditor: + label: formEditor.elements.MultiCheckbox.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..f08fadc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + MultiCheckbox: + formEditor: + predefinedDefaults: + properties: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..fcc4646 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..0e08597 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/200.rst.txt new file mode 100644 index 0000000..b51708c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/200.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/300.rst.txt new file mode 100644 index 0000000..9b3b972 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/300.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..2bb1537 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..30c7d4b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + MultiCheckbox: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/implementationClassName.rst.txt new file mode 100644 index 0000000..b526da7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + MultiCheckbox: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..0101d2e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiCheckbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..841024a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + MultiCheckbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementDescription.rst.txt new file mode 100644 index 0000000..1508442 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..af30c32 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiCheckbox/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiCheckbox.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + MultiCheckbox: + properties: + containerClassAttribute: 'input checkbox' + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect.rst b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect.rst new file mode 100644 index 0000000..ca0d496 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect.rst @@ -0,0 +1,97 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect: + +============= +[MultiSelect] +============= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.implementationclassname: +.. include:: MultiSelect/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.containerclassattribute: +.. include:: MultiSelect/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.elementclassattribute: +.. include:: MultiSelect/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.elementDescription: +.. include:: MultiSelect/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.elementerrorclassattribute: +.. include:: MultiSelect/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.prependOptionLabel: +.. include:: MultiSelect/properties/prependOptionLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.properties.prependOptionValue: +.. include:: MultiSelect/properties/prependOptionValue.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor: +.. include:: MultiSelect/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.100: +.. include:: MultiSelect/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.200: +.. include:: MultiSelect/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.230: +.. include:: MultiSelect/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.250: +.. include:: MultiSelect/formEditor/editors/250.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.300: +.. include:: MultiSelect/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.700: +.. include:: MultiSelect/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.800: +.. include:: MultiSelect/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.900: +.. include:: MultiSelect/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.editors.9999: +.. include:: MultiSelect/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.predefineddefaults: +.. include:: MultiSelect/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10.identifier: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10.editors.100: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10.editors.200: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10.editors.300: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.propertycollections.validators.10.editors.9999: +.. include:: MultiSelect/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.label: +.. include:: MultiSelect/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.group: +.. include:: MultiSelect/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.groupsorting: +.. include:: MultiSelect/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.multiselect.formeditor.iconidentifier: +.. include:: MultiSelect/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor.rst.txt new file mode 100644 index 0000000..6555052 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor.rst.txt @@ -0,0 +1,131 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + MultiSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.MultiSelect.label + group: select + groupSorting: 500 + iconIdentifier: form-multi-select diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..2034bbe --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..a77d795 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..64fa7b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/250.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/250.rst.txt new file mode 100644 index 0000000..749ceda --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/250.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.250 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.250 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..2920b46 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..706c496 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..afb79e1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..4261a3d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/900.rst.txt @@ -0,0 +1,40 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.MultiSelectionMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.MultiSelectionMixin.editor.validators.EmptyValue.label + 20: + value: Count + label: formEditor.elements.MultiSelectionMixin.editor.validators.Count.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..e5bfe21 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + MultiSelect: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/group.rst.txt new file mode 100644 index 0000000..bf29e08 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiSelect: + formEditor: + group: select + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..711f7ca --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiSelect: + formEditor: + groupSorting: 500 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..7001c63 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiSelect: + formEditor: + iconIdentifier: form-multi-select + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/label.rst.txt new file mode 100644 index 0000000..416e597 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiSelect: + formEditor: + label: formEditor.elements.MultiSelect.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..bce6455 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + MultiSelect: + formEditor: + predefinedDefaults: + properties: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..2c2e143 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..43f9e8d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/200.rst.txt new file mode 100644 index 0000000..6c85709 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/200.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/300.rst.txt new file mode 100644 index 0000000..74662d3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/300.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..2fd25a7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..f274f97 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + MultiSelect: + formEditor: + propertyCollections: + validators: + 10: + identifier: Count + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/implementationClassName.rst.txt new file mode 100644 index 0000000..b55f171 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + MultiSelect: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..ad1dd13 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + MultiSelect: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..1e5bf0b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + MultiSelect: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementDescription.rst.txt new file mode 100644 index 0000000..98b90a7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..62e7127 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + MultiSelect: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionLabel.rst.txt new file mode 100644 index 0000000..0c61ae1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionLabel.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +properties.prependOptionLabel +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.prependOptionLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + undefined + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + If set, this label will be shown as first select-option. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionValue.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionValue.rst.txt new file mode 100644 index 0000000..01b1b42 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/MultiSelect/properties/prependOptionValue.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +properties.prependOptionValue +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.MultiSelect.properties.prependOptionValue + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + undefined + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + If set, this value will be set for the first select-option. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Number.rst new file mode 100644 index 0000000..a0f27fb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number.rst @@ -0,0 +1,106 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number: + +======== +[Number] +======== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.implementationclassname: +.. include:: Number/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.properties.containerclassattribute: +.. include:: Number/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.properties.elementclassattribute: +.. include:: Number/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.properties.elementDescription: +.. include:: Number/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.properties.elementerrorclassattribute: +.. include:: Number/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.validators: +.. include:: Number/validators.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor: +.. include:: Number/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.100: +.. include:: Number/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.200: +.. include:: Number/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.230: +.. include:: Number/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.400: +.. include:: Number/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.500: +.. include:: Number/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.550: +.. include:: Number/formEditor/editors/550.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.700: +.. include:: Number/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.800: +.. include:: Number/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.900: +.. include:: Number/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.editors.9999: +.. include:: Number/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.predefineddefaults: +.. include:: Number/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.60: +.. include:: Number/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.60.identifier: +.. include:: Number/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.60.editors.100: +.. include:: Number/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70: +.. include:: Number/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70.identifier: +.. include:: Number/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70.editors.100: +.. include:: Number/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70.editors.200: +.. include:: Number/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70.editors.300: +.. include:: Number/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.propertycollections.validators.70.editors.9999: +.. include:: Number/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.label: +.. include:: Number/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.group: +.. include:: Number/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.groupsorting: +.. include:: Number/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.number.formeditor.iconidentifier: +.. include:: Number/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor.rst.txt new file mode 100644 index 0000000..ba58cbf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor.rst.txt @@ -0,0 +1,152 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Number: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + propertyValidators: + 10: IntegerOrEmpty + 550: + identifier: step + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.step.label + propertyPath: properties.fluidAdditionalAttributes.step + propertyValidators: + 10: Integer + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 60: + value: Number + label: formEditor.elements.Number.editor.validators.Number.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + properties: + fluidAdditionalAttributes: + step: 1 + validators: + - + identifier: Number + propertyCollections: + validators: + 60: + identifier: Number + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Number.editor.header.label + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Number.label + group: html5 + groupSorting: 400 + iconIdentifier: form-number diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..4b993b4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/100.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..a4955cb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..51e1073 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..226a8fc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..6da2e6d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/550.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/550.rst.txt new file mode 100644 index 0000000..b696d05 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/550.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.550 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.550 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 550: + identifier: step + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.step.label + propertyPath: properties.fluidAdditionalAttributes.step + propertyValidators: + 10: Integer + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..3b36558 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..624b6d0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..88b2bdb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/900.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 60: + value: Number + label: formEditor.elements.Number.editor.validators.Number.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..50324d6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Number: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/group.rst.txt new file mode 100644 index 0000000..5dae9cd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/group.rst.txt @@ -0,0 +1,28 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Number: + formEditor: + group: html5 + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..b4db99a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Number: + formEditor: + groupSorting: 400 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..87d5c3a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Number: + formEditor: + iconIdentifier: form-number + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/label.rst.txt new file mode 100644 index 0000000..2b17e51 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Number: + formEditor: + label: formEditor.elements.Number.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..a7576c5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Number: + formEditor: + predefinedDefaults: + defaultValue: '' + properties: + fluidAdditionalAttributes: + step: 1 + validators: + - + identifier: Number + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..a8050ea --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Number: + formEditor: + propertyCollections: + validators: + 60: + identifier: Number + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Number.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..8036662 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Number: + formEditor: + propertyCollections: + validators: + 60: + identifier: Number + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Number.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..d798170 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Number: + formEditor: + propertyCollections: + validators: + 60: + identifier: Number + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Number.editor.header.label + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..06352be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..69b7303 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..1b7ddbb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..392ef9d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..866cc9c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..e5ba789 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Number: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/implementationClassName.rst.txt new file mode 100644 index 0000000..e5083ce --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Number: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..be89d27 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Number: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..d7c41d4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Number: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementDescription.rst.txt new file mode 100644 index 0000000..d740fbd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..7e5e31c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Number: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Number/validators.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Number/validators.rst.txt new file mode 100644 index 0000000..f345021 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Number/validators.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt +validators +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Number.validators + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Number: + validators: + - + identifier: Number + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Predefined validators. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Page.rst new file mode 100644 index 0000000..baa9275 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page.rst @@ -0,0 +1,67 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page: + +====== +[Page] +====== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.implementationclassname: +.. include:: Page/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.renderingoptions._iscompositeformelement: +.. include:: Page/renderingOptions/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.renderingoptions._istoplevelformelement: +.. include:: Page/renderingOptions/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.renderingoptions.nextbuttonlabel: +.. include:: Page/renderingOptions/nextButtonLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.renderingoptions.previousbuttonlabel: +.. include:: Page/renderingOptions/previousButtonLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor: +.. include:: Page/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.editors.100: +.. include:: Page/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.editors.200: +.. include:: Page/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.editors.300: +.. include:: Page/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.editors.400: +.. include:: Page/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.editors.9999: +.. include:: Page/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.predefineddefaults: +.. include:: Page/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor._iscompositeformelement: +.. include:: Page/formEditor/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor._istoplevelformelement: +.. include:: Page/formEditor/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.label: +.. include:: Page/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.group: +.. include:: Page/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.groupsorting: +.. include:: Page/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.page.formeditor.iconidentifier: +.. include:: Page/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor.rst.txt new file mode 100644 index 0000000..627bbb5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor.rst.txt @@ -0,0 +1,56 @@ +.. include:: /Includes.rst.txt + +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Page: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Page.editor.label.label + propertyPath: label + 300: + identifier: 'previousButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Page.editor.previousButtonLabel.label' + propertyPath: 'renderingOptions.previousButtonLabel' + 400: + identifier: 'nextButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Page.editor.nextButtonLabel.label' + propertyPath: 'renderingOptions.nextButtonLabel' + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + renderingOptions: + previousButtonLabel: 'formEditor.elements.Page.editor.previousButtonLabel.value' + nextButtonLabel: 'formEditor.elements.Page.editor.nextButtonLabel.value' + label: formEditor.elements.Page.label + group: page + groupSorting: 100 + _isTopLevelFormElement: true + _isCompositeFormElement: true + iconIdentifier: form-page diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..d71a53a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isCompositeFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isCompositeFormElement +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Page: + formEditor: + _isCompositeFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..5838c76 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/_isTopLevelFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isTopLevelFormElement +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Page: + formEditor: + _isTopLevelFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..4529bdd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Page: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..5cec555 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Page: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.Page.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..f8a87b0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 300: + identifier: 'previousButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Page.editor.previousButtonLabel.label' + propertyPath: 'renderingOptions.previousButtonLabel' diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..bdd0350 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/400.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 400: + identifier: 'nextButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.Page.editor.nextButtonLabel.label' + propertyPath: 'renderingOptions.nextButtonLabel' diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..a6eb982 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Page: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/group.rst.txt new file mode 100644 index 0000000..62b6b20 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Page: + formEditor: + group: page + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..a08ed34 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Page: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..af57d34 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Page: + formEditor: + iconIdentifier: form-page + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/label.rst.txt new file mode 100644 index 0000000..6c56e24 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Page: + formEditor: + label: formEditor.elements.Page.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..4a9a720 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Page: + formEditor: + predefinedDefaults: + renderingOptions: + previousButtonLabel: 'formEditor.elements.Page.editor.previousButtonLabel.value' + nextButtonLabel: 'formEditor.elements.Page.editor.nextButtonLabel.value' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/implementationClassName.rst.txt new file mode 100644 index 0000000..a650336 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Page: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Page + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..714dc12 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isCompositeFormElement.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions._isCompositeFormElement +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.renderingOptions._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Page: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: true + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..e612adc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/_isTopLevelFormElement.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions._isTopLevelFormElement +--------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.renderingOptions._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Page: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: true + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/nextButtonLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/nextButtonLabel.rst.txt new file mode 100644 index 0000000..81d2d7e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/nextButtonLabel.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions.nextButtonLabel +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.renderingOptions.nextButtonLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Page: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the "next page" Button. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/previousButtonLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/previousButtonLabel.rst.txt new file mode 100644 index 0000000..de05ca8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Page/renderingOptions/previousButtonLabel.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions.previousButtonLabel +------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.Page.renderingOptions.previousButtonLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Page: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the "previous page" Button. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Password.rst new file mode 100644 index 0000000..69002bd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password.rst @@ -0,0 +1,184 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password: + +========== +[Password] +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.implementationclassname: +.. include:: Password/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.properties.containerclassattribute: +.. include:: Password/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.properties.elementclassattribute: +.. include:: Password/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.properties.elementDescription: +.. include:: Password/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.properties.elementerrorclassattribute: +.. include:: Password/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor: +.. include:: Password/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.100: +.. include:: Password/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.200: +.. include:: Password/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.230: +.. include:: Password/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.400: +.. include:: Password/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.500: +.. include:: Password/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.700: +.. include:: Password/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.800: +.. include:: Password/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.900: +.. include:: Password/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.editors.9999: +.. include:: Password/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.predefineddefaults: +.. include:: Password/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.10: +.. include:: Password/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.10.identifier: +.. include:: Password/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.10.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.10.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.20: +.. include:: Password/formEditor/propertyCollections/validators/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.20.identifier: +.. include:: Password/formEditor/propertyCollections/validators/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.20.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.20.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30: +.. include:: Password/formEditor/propertyCollections/validators/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30.identifier: +.. include:: Password/formEditor/propertyCollections/validators/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30.editors.200: +.. include:: Password/formEditor/propertyCollections/validators/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30.editors.300: +.. include:: Password/formEditor/propertyCollections/validators/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.30.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.40: +.. include:: Password/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.40.identifier: +.. include:: Password/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.40.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.40.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.50: +.. include:: Password/formEditor/propertyCollections/validators/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.50.identifier: +.. include:: Password/formEditor/propertyCollections/validators/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.50.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.50.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.60: +.. include:: Password/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.60.identifier: +.. include:: Password/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.60.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.60.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70: +.. include:: Password/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70.identifier: +.. include:: Password/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70.editors.200: +.. include:: Password/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70.editors.300: +.. include:: Password/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.70.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.80: +.. include:: Password/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.80.identifier: +.. include:: Password/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.80.editors.100: +.. include:: Password/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.80.editors.200: +.. include:: Password/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.propertycollections.validators.80.editors.9999: +.. include:: Password/formEditor/propertyCollections/validators/80/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.label: +.. include:: Password/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.group: +.. include:: Password/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.groupsorting: +.. include:: Password/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.password.formeditor.iconidentifier: +.. include:: Password/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor.rst.txt new file mode 100644 index 0000000..5b71bc8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor.rst.txt @@ -0,0 +1,240 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Password: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Password.label + group: input + groupSorting: 300 + iconIdentifier: form-password diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..74d75b4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..c103bbf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..d34b46a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..cb3b050 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..99a8b5f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..777bd9b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..2d8df5f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..f2d4392 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/900.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..89da0f9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Password: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/group.rst.txt new file mode 100644 index 0000000..a288563 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Password: + formEditor: + group: input + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..4d8a835 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Password: + formEditor: + groupSorting: 300 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..90ef86a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Password: + formEditor: + iconIdentifier: form-password + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/label.rst.txt new file mode 100644 index 0000000..b4ac401 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Password: + formEditor: + label: formEditor.elements.Password.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..c3fb54f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Password: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..b095c17 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..4ef2712 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..df490c5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..32b0dc0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20.rst.txt new file mode 100644 index 0000000..6fc020b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/100.rst.txt new file mode 100644 index 0000000..01ecd9b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/9999.rst.txt new file mode 100644 index 0000000..4192a78 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/identifier.rst.txt new file mode 100644 index 0000000..b8880a5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/20/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30.rst.txt new file mode 100644 index 0000000..90065cf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/100.rst.txt new file mode 100644 index 0000000..5333467 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/200.rst.txt new file mode 100644 index 0000000..8370c71 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/300.rst.txt new file mode 100644 index 0000000..2c2aac4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/9999.rst.txt new file mode 100644 index 0000000..89bb2bf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/identifier.rst.txt new file mode 100644 index 0000000..9ef4659 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/30/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..85fc0f6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..6f91a12 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/9999.rst.txt new file mode 100644 index 0000000..c145c16 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..e4e3470 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50.rst.txt new file mode 100644 index 0000000..7c3ad19 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/100.rst.txt new file mode 100644 index 0000000..311431c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/9999.rst.txt new file mode 100644 index 0000000..e799b6c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/identifier.rst.txt new file mode 100644 index 0000000..b6ce551 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/50/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..7d8c130 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..4444a6c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/9999.rst.txt new file mode 100644 index 0000000..21530c0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..8886ce9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..2b595b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..a8361d8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..1746fad --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..e8d7ea0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..d924daa --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..d6646ec --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..8f8472d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Password: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..ef3f2c0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..ea37f80 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/9999.rst.txt new file mode 100644 index 0000000..002de6b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Password: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..be9fccf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Password: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/implementationClassName.rst.txt new file mode 100644 index 0000000..611c455 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Password: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..023645e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Password: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..e0aac0d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Password: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementDescription.rst.txt new file mode 100644 index 0000000..06a87cb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..5a46915 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Password/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Password.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Password: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton.rst b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton.rst new file mode 100644 index 0000000..36c5406 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton.rst @@ -0,0 +1,67 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton: + +============= +[RadioButton] +============= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.implementationclassname: +.. include:: RadioButton/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.properties.containerclassattribute: +.. include:: RadioButton/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.properties.elementclassattribute: +.. include:: RadioButton/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.properties.elementDescription: +.. include:: RadioButton/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.properties.elementerrorclassattribute: +.. include:: RadioButton/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor: +.. include:: RadioButton/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.100: +.. include:: RadioButton/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.200: +.. include:: RadioButton/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.230: +.. include:: RadioButton/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.300: +.. include:: RadioButton/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.700: +.. include:: RadioButton/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.800: +.. include:: RadioButton/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.editors.9999: +.. include:: RadioButton/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.predefineddefaults: +.. include:: RadioButton/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.label: +.. include:: RadioButton/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.group: +.. include:: RadioButton/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.groupsorting: +.. include:: RadioButton/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.radiobutton.formeditor.iconidentifier: +.. include:: RadioButton/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor.rst.txt new file mode 100644 index 0000000..2895039 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor.rst.txt @@ -0,0 +1,87 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + RadioButton: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + label: formEditor.elements.RadioButton.label + group: select + groupSorting: 300 + iconIdentifier: form-radio-button diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..eb188f5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..e808e57 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..e95a98b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..2f09272 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..a120c79 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..9bb00cd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..1b2ce61 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + RadioButton: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/group.rst.txt new file mode 100644 index 0000000..8d798ef --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RadioButton: + formEditor: + group: select + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..7b1d1a9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RadioButton: + formEditor: + groupSorting: 300 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..6e67ba3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RadioButton: + formEditor: + iconIdentifier: form-radio-button + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/label.rst.txt new file mode 100644 index 0000000..8cdecca --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RadioButton: + formEditor: + label: formEditor.elements.RadioButton.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..667c95f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + RadioButton: + formEditor: + predefinedDefaults: + properties: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/implementationClassName.rst.txt new file mode 100644 index 0000000..1da723e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + RadioButton: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..ef38157 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RadioButton: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..6182175 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + RadioButton: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementDescription.rst.txt new file mode 100644 index 0000000..cda6c1c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..071fa3d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/RadioButton/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.RadioButton.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + RadioButton: + properties: + containerClassAttribute: input + elementClassAttribute: xlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect.rst b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect.rst new file mode 100644 index 0000000..0bdf400 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect.rst @@ -0,0 +1,76 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect: + +============== +[SingleSelect] +============== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.implementationclassname: +.. include:: SingleSelect/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.containerclassattribute: +.. include:: SingleSelect/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.elementclassattribute: +.. include:: SingleSelect/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.elementDescription: +.. include:: SingleSelect/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.elementerrorclassattribute: +.. include:: SingleSelect/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.prependOptionLabel: +.. include:: SingleSelect/properties/prependOptionLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.properties.prependOptionValue: +.. include:: SingleSelect/properties/prependOptionValue.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor: +.. include:: SingleSelect/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.100: +.. include:: SingleSelect/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.200: +.. include:: SingleSelect/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.230: +.. include:: SingleSelect/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.250: +.. include:: SingleSelect/formEditor/editors/250.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.300: +.. include:: SingleSelect/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.700: +.. include:: SingleSelect/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.800: +.. include:: SingleSelect/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.editors.9999: +.. include:: SingleSelect/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.predefineddefaults: +.. include:: SingleSelect/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.label: +.. include:: SingleSelect/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.group: +.. include:: SingleSelect/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.groupsorting: +.. include:: SingleSelect/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.singleselect.formeditor.iconidentifier: +.. include:: SingleSelect/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor.rst.txt new file mode 100644 index 0000000..c1d7583 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor.rst.txt @@ -0,0 +1,94 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + SingleSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + options: { } + label: formEditor.elements.SingleSelect.label + group: select + groupSorting: 200 + iconIdentifier: form-single-select diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..a907692 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..66dcc4c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..049afb2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/250.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/250.rst.txt new file mode 100644 index 0000000..580c15f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/250.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.250 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.250 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 250: + identifier: inactiveOption + templateName: Inspector-TextEditor + label: formEditor.elements.SelectionMixin.editor.inactiveOption.label + propertyPath: properties.prependOptionLabel + description: formEditor.elements.SelectionMixin.editor.inactiveOption.description + doNotSetIfPropertyValueIsEmpty: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..503a5d1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[PropertyGridEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 300: + identifier: options + templateName: Inspector-PropertyGridEditor + label: formEditor.elements.SelectionMixin.editor.options.label + propertyPath: properties.options + isSortable: true + enableAddRow: true + enableDeleteRow: true + removeLastAvailableRowFlashMessageTitle: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageTitle + removeLastAvailableRowFlashMessageMessage: formEditor.elements.SelectionMixin.editor.options.removeLastAvailableRowFlashMessageMessage + multiSelection: false diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..63493c8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..6849fab --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/800.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..03ba3b9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SingleSelect: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/group.rst.txt new file mode 100644 index 0000000..fd8e389 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SingleSelect: + formEditor: + group: select + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..3ca63c2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SingleSelect: + formEditor: + groupSorting: 200 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..7fb81da --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SingleSelect: + formEditor: + iconIdentifier: form-single-select + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/label.rst.txt new file mode 100644 index 0000000..16c7293 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SingleSelect: + formEditor: + label: formEditor.elements.SingleSelect.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..dd1c61a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + SingleSelect: + formEditor: + predefinedDefaults: + properties: + options: { } + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/implementationClassName.rst.txt new file mode 100644 index 0000000..6a8629e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + SingleSelect: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..b6cbc24 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SingleSelect: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..5b25028 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + SingleSelect: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementDescription.rst.txt new file mode 100644 index 0000000..45c3d0d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..278ce12 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + SingleSelect: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionLabel.rst.txt new file mode 100644 index 0000000..ea14137 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionLabel.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +properties.prependOptionLabel +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.prependOptionLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + undefined + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + If set, this label will be shown as first select-option. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionValue.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionValue.rst.txt new file mode 100644 index 0000000..ccec179 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SingleSelect/properties/prependOptionValue.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +properties.prependOptionValue +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SingleSelect.properties.prependOptionValue + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + undefined + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + If set, this value will be set for the first select-option. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText.rst b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText.rst new file mode 100644 index 0000000..e60377d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText.rst @@ -0,0 +1,52 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext: + +============ +[StaticText] +============ + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.implementationclassname: +.. include:: StaticText/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.properties.text: +.. include:: StaticText/properties/text.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor: +.. include:: StaticText/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.editors.100: +.. include:: StaticText/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.editors.200: +.. include:: StaticText/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.editors.300: +.. include:: StaticText/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.editors.700: +.. include:: StaticText/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.editors.9999: +.. include:: StaticText/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.predefineddefaults: +.. include:: StaticText/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.label: +.. include:: StaticText/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.group: +.. include:: StaticText/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.groupsorting: +.. include:: StaticText/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.statictext.formeditor.iconidentifier: +.. include:: StaticText/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor.rst.txt new file mode 100644 index 0000000..c4b9d8c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor.rst.txt @@ -0,0 +1,70 @@ +.. include:: /Includes.rst.txt + +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + StaticText: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.ReadOnlyFormElement.editor.label.label + propertyPath: label + 300: + identifier: staticText + templateName: Inspector-TextareaEditor + label: formEditor.elements.StaticText.editor.staticText.label + propertyPath: properties.text + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + properties: + text: '' + label: formEditor.elements.StaticText.label + group: custom + groupSorting: 600 + iconIdentifier: form-static-text diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..1e7d374 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + StaticText: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..735aee4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + StaticText: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.ReadOnlyFormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..fdb88b8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextareaEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + StaticText: + formEditor: + editors: + 300: + identifier: staticText + templateName: Inspector-TextareaEditor + label: formEditor.elements.StaticText.editor.staticText.label + propertyPath: properties.text diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..42fec99 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/700.rst.txt @@ -0,0 +1,50 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + StaticText: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..4ef1245 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + StaticText: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/group.rst.txt new file mode 100644 index 0000000..4dd901e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StaticText: + formEditor: + group: custom + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..c33982c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StaticText: + formEditor: + groupSorting: 600 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..f5502c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StaticText: + formEditor: + iconIdentifier: form-static-text + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/label.rst.txt new file mode 100644 index 0000000..bed77c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StaticText: + formEditor: + label: formEditor.elements.StaticText.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..bdd8e62 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + StaticText: + formEditor: + predefinedDefaults: + properties: + text: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/implementationClassName.rst.txt new file mode 100644 index 0000000..9a36810 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + StaticText: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/properties/text.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/properties/text.rst.txt new file mode 100644 index 0000000..ede3983 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/StaticText/properties/text.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +properties.text +--------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.StaticText.properties.text + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StaticText: + properties: + text: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The text to display. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage.rst b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage.rst new file mode 100644 index 0000000..c8e6fda --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage.rst @@ -0,0 +1,67 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarysummarypage: + +============= +[SummaryPage] +============= + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarysummarypage-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.implementationclassname: +.. include:: SummaryPage/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.renderingoptions._iscompositeformelement: +.. include:: SummaryPage/renderingOptions/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.renderingoptions._istoplevelformelement: +.. include:: SummaryPage/renderingOptions/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.renderingoptions.nextbuttonlabel: +.. include:: SummaryPage/renderingOptions/nextButtonLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.renderingoptions.previousbuttonlabel: +.. include:: SummaryPage/renderingOptions/previousButtonLabel.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor: +.. include:: SummaryPage/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.editors.100: +.. include:: SummaryPage/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.editors.200: +.. include:: SummaryPage/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.editors.300: +.. include:: SummaryPage/formEditor/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.editors.400: +.. include:: SummaryPage/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.editors.9999: +.. include:: SummaryPage/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.predefineddefaults: +.. include:: SummaryPage/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor._iscompositeformelement: +.. include:: SummaryPage/formEditor/_isCompositeFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor._istoplevelformelement: +.. include:: SummaryPage/formEditor/_isTopLevelFormElement.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.label: +.. include:: SummaryPage/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.group: +.. include:: SummaryPage/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.groupsorting: +.. include:: SummaryPage/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.summarypage.formeditor.iconidentifier: +.. include:: SummaryPage/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor.rst.txt new file mode 100644 index 0000000..eb6d0d1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor.rst.txt @@ -0,0 +1,56 @@ +.. include:: /Includes.rst.txt + +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + SummaryPage: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.SummaryPage.editor.label.label + propertyPath: label + 300: + identifier: 'previousButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.SummaryPage.editor.previousButtonLabel.label' + propertyPath: 'renderingOptions.previousButtonLabel' + 400: + identifier: 'nextButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.SummaryPage.editor.nextButtonLabel.label' + propertyPath: 'renderingOptions.nextButtonLabel' + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + renderingOptions: + previousButtonLabel: 'formEditor.elements.SummaryPage.editor.previousButtonLabel.value' + nextButtonLabel: 'formEditor.elements.SummaryPage.editor.nextButtonLabel.value' + label: formEditor.elements.SummaryPage.label + group: page + groupSorting: 200 + _isTopLevelFormElement: true + _isCompositeFormElement: false + iconIdentifier: form-summary-page diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..746d00b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isCompositeFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isCompositeFormElement +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + SummaryPage: + formEditor: + _isCompositeFormElement: false + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..412ed63 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/_isTopLevelFormElement.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor._isTopLevelFormElement +--------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + SummaryPage: + formEditor: + _isTopLevelFormElement: true + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..5642347 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SummaryPage: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..e913f04 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SummaryPage: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.SummaryPage.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/300.rst.txt new file mode 100644 index 0000000..0233413 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/300.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.300 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 300: + identifier: 'previousButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.SummaryPage.editor.previousButtonLabel.label' + propertyPath: 'renderingOptions.previousButtonLabel' diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..e0ba2af --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/400.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Form: + formEditor: + editors: + 400: + identifier: 'nextButtonLabel' + templateName: 'Inspector-TextEditor' + label: 'formEditor.elements.SummaryPage.editor.nextButtonLabel.label' + propertyPath: 'renderingOptions.nextButtonLabel' diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..5ee1891 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + SummaryPage: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/group.rst.txt new file mode 100644 index 0000000..667cbda --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SummaryPage: + formEditor: + group: page + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..2cca72a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SummaryPage: + formEditor: + groupSorting: 200 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..5a7f00f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SummaryPage: + formEditor: + iconIdentifier: form-summary-page + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/label.rst.txt new file mode 100644 index 0000000..7640e6b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SummaryPage: + formEditor: + label: formEditor.elements.SummaryPage.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..3a2fce2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + SummaryPage: + formEditor: + predefinedDefaults: + renderingOptions: + previousButtonLabel: 'formEditor.elements.SummaryPage.editor.previousButtonLabel.value' + nextButtonLabel: 'formEditor.elements.SummaryPage.editor.nextButtonLabel.value' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/implementationClassName.rst.txt new file mode 100644 index 0000000..973ff69 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + SummaryPage: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\Page + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isCompositeFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isCompositeFormElement.rst.txt new file mode 100644 index 0000000..755a9e7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isCompositeFormElement.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions._isCompositeFormElement +---------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.renderingOptions._isCompositeFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + SummaryPage: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element contains child form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isTopLevelFormElement.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isTopLevelFormElement.rst.txt new file mode 100644 index 0000000..072d9e4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/_isTopLevelFormElement.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions._isTopLevelFormElement +--------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.renderingOptions._isTopLevelFormElement + +:aspect:`Data type` + bool + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + SummaryPage: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Internal control setting to define that the form element must not have a parent form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/nextButtonLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/nextButtonLabel.rst.txt new file mode 100644 index 0000000..df492d3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/nextButtonLabel.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions.nextButtonLabel +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.renderingOptions.nextButtonLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + SummaryPage: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the "next page" Button. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/previousButtonLabel.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/previousButtonLabel.rst.txt new file mode 100644 index 0000000..e31d6c7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/SummaryPage/renderingOptions/previousButtonLabel.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +renderingOptions.previousButtonLabel +------------------------------------ + +:aspect:`Option path` + prototypes..formElementsDefinition.SummaryPage.renderingOptions.previousButtonLabel + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + SummaryPage: + renderingOptions: + _isTopLevelFormElement: true + _isCompositeFormElement: false + nextButtonLabel: 'next Page' + previousButtonLabel: 'previous Page' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The label for the "previous page" Button. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone.rst new file mode 100644 index 0000000..e42af76 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone.rst @@ -0,0 +1,88 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone: + +=========== +[Telephone] +=========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.implementationclassname: +.. include:: Telephone/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.properties.containerclassattribute: +.. include:: Telephone/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.properties.elementclassattribute: +.. include:: Telephone/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.properties.elementDescription: +.. include:: Telephone/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.properties.elementerrorclassattribute: +.. include:: Telephone/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.validators: +.. include:: Telephone/validators.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor: +.. include:: Telephone/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.100: +.. include:: Telephone/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.200: +.. include:: Telephone/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.230: +.. include:: Telephone/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.400: +.. include:: Telephone/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.500: +.. include:: Telephone/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.700: +.. include:: Telephone/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.800: +.. include:: Telephone/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.900: +.. include:: Telephone/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.editors.9999: +.. include:: Telephone/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.predefineddefaults: +.. include:: Telephone/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.propertycollections.validators.80: +.. include:: Telephone/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.propertycollections.validators.80.identifier: +.. include:: Telephone/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.propertycollections.validators.80.editors.100: +.. include:: Telephone/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.propertycollections.validators.80.editors.200: +.. include:: Telephone/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.label: +.. include:: Telephone/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.group: +.. include:: Telephone/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.groupsorting: +.. include:: Telephone/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.telephone.formeditor.iconidentifier: +.. include:: Telephone/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor.rst.txt new file mode 100644 index 0000000..90b1e23 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor.rst.txt @@ -0,0 +1,112 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Telephone: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + label: formEditor.elements.Telephone.label + group: html5 + groupSorting: 200 + iconIdentifier: form-telephone diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..8e584b3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/100.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..41dd184 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..947b2a2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..eb42a13 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..57ed066 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..0f9960b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/700.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..bc22c80 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..bb93189 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/900.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..676247e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Telephone: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/group.rst.txt new file mode 100644 index 0000000..f879c04 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/group.rst.txt @@ -0,0 +1,28 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Telephone: + formEditor: + group: html5 + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..28d373d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Telephone: + formEditor: + groupSorting: 200 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..15b8a90 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Telephone: + formEditor: + iconIdentifier: form-telephone + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/label.rst.txt new file mode 100644 index 0000000..70a06e4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Telephone: + formEditor: + label: formEditor.elements.Telephone.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..ed0e9a0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Telephone: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..16c9c6b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Telephone: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..e7bdf3c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..b28d456 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Telephone: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..158458e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Telephone: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/implementationClassName.rst.txt new file mode 100644 index 0000000..1d6119d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Telephone: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..397822f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Telephone: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..618293b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Telephone: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementDescription.rst.txt new file mode 100644 index 0000000..8dea7f2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..432543e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Telephone: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/validators.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/validators.rst.txt new file mode 100644 index 0000000..e0772b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Telephone/validators.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +validators +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Telephone.validators + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Telephone: + validators: + - + identifier: RegularExpression + options: + regularExpression: '/^.*$/' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Predefined validators. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Text.rst new file mode 100644 index 0000000..32f4bc7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text.rst @@ -0,0 +1,184 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text: + +====== +[Text] +====== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.implementationclassname: +.. include:: Text/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.properties.containerclassattribute: +.. include:: Text/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.properties.elementclassattribute: +.. include:: Text/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.properties.elementDescription: +.. include:: Text/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.properties.elementerrorclassattribute: +.. include:: Text/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor: +.. include:: Text/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.100: +.. include:: Text/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.200: +.. include:: Text/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.230: +.. include:: Text/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.400: +.. include:: Text/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.500: +.. include:: Text/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.700: +.. include:: Text/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.800: +.. include:: Text/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.900: +.. include:: Text/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.editors.9999: +.. include:: Text/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.predefineddefaults: +.. include:: Text/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.10: +.. include:: Text/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.10.identifier: +.. include:: Text/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.10.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.10.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.20: +.. include:: Text/formEditor/propertyCollections/validators/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.20.identifier: +.. include:: Text/formEditor/propertyCollections/validators/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.20.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.20.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30: +.. include:: Text/formEditor/propertyCollections/validators/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30.identifier: +.. include:: Text/formEditor/propertyCollections/validators/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30.editors.200: +.. include:: Text/formEditor/propertyCollections/validators/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30.editors.300: +.. include:: Text/formEditor/propertyCollections/validators/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.30.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.40: +.. include:: Text/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.40.identifier: +.. include:: Text/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.40.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.40.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.50: +.. include:: Text/formEditor/propertyCollections/validators/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.50.identifier: +.. include:: Text/formEditor/propertyCollections/validators/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.50.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.50.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.60: +.. include:: Text/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.60.identifier: +.. include:: Text/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.60.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.60.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70: +.. include:: Text/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70.identifier: +.. include:: Text/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70.editors.200: +.. include:: Text/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70.editors.300: +.. include:: Text/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.70.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.80: +.. include:: Text/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.80.identifier: +.. include:: Text/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.80.editors.100: +.. include:: Text/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.80.editors.200: +.. include:: Text/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.propertycollections.validators.80.editors.9999: +.. include:: Text/formEditor/propertyCollections/validators/80/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.label: +.. include:: Text/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.group: +.. include:: Text/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.groupsorting: +.. include:: Text/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.text.formeditor.iconidentifier: +.. include:: Text/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor.rst.txt new file mode 100644 index 0000000..79047ad --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor.rst.txt @@ -0,0 +1,240 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Text: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Text.label + group: input + groupSorting: 100 + iconIdentifier: form-text diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..36c96f5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/100.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..b3a24a5 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..9caea2b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..82f1123 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..3818c3e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..2d743f1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/700.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..94a8d38 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/800.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..56c82dd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/900.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..f835d04 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Text: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/group.rst.txt new file mode 100644 index 0000000..a088b7b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Text: + formEditor: + group: input + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..e5d1156 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Text: + formEditor: + groupSorting: 100 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..fd98e59 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Text: + formEditor: + iconIdentifier: form-text + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/label.rst.txt new file mode 100644 index 0000000..34be80b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Text: + formEditor: + label: formEditor.elements.Text.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..7d105e6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Text: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..bc079f2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..6b8eae0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..16b7052 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..034cfdc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20.rst.txt new file mode 100644 index 0000000..7fea11a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/100.rst.txt new file mode 100644 index 0000000..d967d1e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/9999.rst.txt new file mode 100644 index 0000000..f255ddd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/identifier.rst.txt new file mode 100644 index 0000000..2ce70e4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/20/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30.rst.txt new file mode 100644 index 0000000..96c1ed4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/100.rst.txt new file mode 100644 index 0000000..9e36552 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/200.rst.txt new file mode 100644 index 0000000..b0dfc06 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/300.rst.txt new file mode 100644 index 0000000..cf32b81 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/9999.rst.txt new file mode 100644 index 0000000..8b330c7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/identifier.rst.txt new file mode 100644 index 0000000..dbc6d76 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/30/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..97c9f20 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..637f895 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/9999.rst.txt new file mode 100644 index 0000000..d4dc9a1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..f4a1c04 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50.rst.txt new file mode 100644 index 0000000..b2eb23a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/100.rst.txt new file mode 100644 index 0000000..e2f5dee --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/9999.rst.txt new file mode 100644 index 0000000..e6935a8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/identifier.rst.txt new file mode 100644 index 0000000..fc846b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/50/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..bd17447 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..010c71a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/9999.rst.txt new file mode 100644 index 0000000..7d99e0d --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..044a5c0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..e9af9db --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..caf4228 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..362a381 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..f235705 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..a6bbc62 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..33da6a9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..ce6d535 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..e7bdf3c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..251e38f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/9999.rst.txt new file mode 100644 index 0000000..c4377e3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..46ecb23 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/implementationClassName.rst.txt new file mode 100644 index 0000000..29446fd --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Text: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..71481d8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Text: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..288b99f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Text: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementDescription.rst.txt new file mode 100644 index 0000000..cd68a17 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..c51e6c0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Text/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Text: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea.rst new file mode 100644 index 0000000..73a078a --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea.rst @@ -0,0 +1,184 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textareaarea: + +========== +[Textarea] +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textareaarea-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.implementationclassname: +.. include:: Textarea/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.properties.containerclassattribute: +.. include:: Textarea/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.properties.elementclassattribute: +.. include:: Textarea/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.properties.elementDescription: +.. include:: Textarea/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.properties.elementerrorclassattribute: +.. include:: Textarea/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor: +.. include:: Textarea/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.100: +.. include:: Textarea/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.200: +.. include:: Textarea/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.230: +.. include:: Textarea/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.400: +.. include:: Textarea/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.500: +.. include:: Textarea/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.700: +.. include:: Textarea/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.800: +.. include:: Textarea/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.900: +.. include:: Textarea/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.editors.9999: +.. include:: Textarea/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.predefineddefaults: +.. include:: Textarea/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.10: +.. include:: Textarea/formEditor/propertyCollections/validators/10.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.10.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/10/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.10.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/10/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.10.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/10/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.20: +.. include:: Textarea/formEditor/propertyCollections/validators/20.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.20.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/20/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.20.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/20/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.20.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/20/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30: +.. include:: Textarea/formEditor/propertyCollections/validators/30.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/30/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/30/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30.editors.200: +.. include:: Textarea/formEditor/propertyCollections/validators/30/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30.editors.300: +.. include:: Textarea/formEditor/propertyCollections/validators/30/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.30.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/30/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.40: +.. include:: Textarea/formEditor/propertyCollections/validators/40.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.40.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/40/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.40.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/40/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.40.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/40/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.50: +.. include:: Textarea/formEditor/propertyCollections/validators/50.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.50.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/50/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.50.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/50/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.50.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/50/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.60: +.. include:: Textarea/formEditor/propertyCollections/validators/60.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.60.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/60/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.60.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/60/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.60.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/60/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70: +.. include:: Textarea/formEditor/propertyCollections/validators/70.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/70/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/70/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70.editors.200: +.. include:: Textarea/formEditor/propertyCollections/validators/70/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70.editors.300: +.. include:: Textarea/formEditor/propertyCollections/validators/70/editors/300.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.70.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/70/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.80: +.. include:: Textarea/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.80.identifier: +.. include:: Textarea/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.80.editors.100: +.. include:: Textarea/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.80.editors.200: +.. include:: Textarea/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.propertycollections.validators.80.editors.9999: +.. include:: Textarea/formEditor/propertyCollections/validators/80/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.label: +.. include:: Textarea/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.group: +.. include:: Textarea/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.groupsorting: +.. include:: Textarea/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.textarea.formeditor.iconidentifier: +.. include:: Textarea/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor.rst.txt new file mode 100644 index 0000000..bccb407 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor.rst.txt @@ -0,0 +1,237 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Textarea: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + predefinedDefaults: + defaultValue: '' + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + label: formEditor.elements.Textarea.label + group: input + groupSorting: 200 + iconIdentifier: form-textarea diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..ff8f768 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/100.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..91ac17c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/200.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..95b0584 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..bdc3c0c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/400.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..580d795 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/500.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..e1db991 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/700.rst.txt @@ -0,0 +1,49 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..66a6531 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..0c9fc4b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/900.rst.txt @@ -0,0 +1,54 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 20: + value: Alphanumeric + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + 40: + value: StringLength + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + 50: + value: EmailAddress + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + 60: + value: Integer + label: formEditor.elements.TextMixin.editor.validators.Integer.label + 70: + value: Float + label: formEditor.elements.TextMixin.editor.validators.Float.label + 80: + value: NumberRange + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..5b101b4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/editors/9999.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Textarea: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/group.rst.txt new file mode 100644 index 0000000..15057d3 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/group.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Textarea: + formEditor: + group: input + +:aspect:`Default value` + Depends (see :ref:`concrete element configuration `) + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..cdd744f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Textarea: + formEditor: + groupSorting: 200 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..ff59652 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Textarea: + formEditor: + iconIdentifier: form-textarea + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/label.rst.txt new file mode 100644 index 0000000..e430a14 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Textarea: + formEditor: + label: formEditor.elements.Textarea.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..17fcb0b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Textarea: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10.rst.txt new file mode 100644 index 0000000..8b92666 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.10 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/100.rst.txt new file mode 100644 index 0000000..eecdae1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.10.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Alphanumeric.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/9999.rst.txt new file mode 100644 index 0000000..3460796 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.10.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.10.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/identifier.rst.txt new file mode 100644 index 0000000..4041dbb --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/10/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.10.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.10.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 10: + identifier: Alphanumeric + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20.rst.txt new file mode 100644 index 0000000..96c66d2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.20 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/100.rst.txt new file mode 100644 index 0000000..5748148 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.20.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Text.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/9999.rst.txt new file mode 100644 index 0000000..ba29173 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.20.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.20.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/identifier.rst.txt new file mode 100644 index 0000000..240f236 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/20/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.20.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.20.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 20: + identifier: Text + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30.rst.txt new file mode 100644 index 0000000..c6d97aa --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/100.rst.txt new file mode 100644 index 0000000..cd9aa07 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.StringLength.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/200.rst.txt new file mode 100644 index 0000000..a116105 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.minlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/300.rst.txt new file mode 100644 index 0000000..93be83c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/300.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.maxlength + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/9999.rst.txt new file mode 100644 index 0000000..75d0606 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.30.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/identifier.rst.txt new file mode 100644 index 0000000..5864358 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/30/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.30.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.30.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 30: + identifier: StringLength + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40.rst.txt new file mode 100644 index 0000000..2722657 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.40 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/100.rst.txt new file mode 100644 index 0000000..80e1d36 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.40.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.EmailAddress.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/9999.rst.txt new file mode 100644 index 0000000..c5ea81e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.40.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.40.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/identifier.rst.txt new file mode 100644 index 0000000..dab4c24 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/40/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.40.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.40.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 40: + identifier: EmailAddress + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50.rst.txt new file mode 100644 index 0000000..eb726c2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.50 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/100.rst.txt new file mode 100644 index 0000000..7ffd242 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.50.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Integer.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/9999.rst.txt new file mode 100644 index 0000000..71596be --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.50.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.50.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/identifier.rst.txt new file mode 100644 index 0000000..5787275 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/50/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.50.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.50.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 50: + identifier: Integer + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60.rst.txt new file mode 100644 index 0000000..1f03a61 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.60 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/100.rst.txt new file mode 100644 index 0000000..cfa7a44 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.60.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.Float.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/9999.rst.txt new file mode 100644 index 0000000..a7978d4 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.60.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.60.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/identifier.rst.txt new file mode 100644 index 0000000..04bf871 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/60/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.60.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.60.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 60: + identifier: Float + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70.rst.txt new file mode 100644 index 0000000..44eb3d2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70.rst.txt @@ -0,0 +1,55 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/100.rst.txt new file mode 100644 index 0000000..db0bd3f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.NumberRange.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/200.rst.txt new file mode 100644 index 0000000..9e1b29b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/200.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 200: + identifier: minimum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.minimum.label + propertyPath: options.minimum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.min diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/300.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/300.rst.txt new file mode 100644 index 0000000..57ac0da --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/300.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.300 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70.editors.300 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 300: + identifier: maximum + templateName: Inspector-TextEditor + label: formEditor.elements.MinimumMaximumEditorsMixin.editor.maximum.label + propertyPath: options.maximum + propertyValidators: + 10: Integer + additionalElementPropertyPaths: + 10: properties.fluidAdditionalAttributes.max diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/9999.rst.txt new file mode 100644 index 0000000..2c9aa8e --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.70.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/identifier.rst.txt new file mode 100644 index 0000000..46ca243 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/70/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.70.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.70.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 70: + identifier: NumberRange + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..a05daa8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Textarea: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..ed83564 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..f5d05c0 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/9999.rst.txt new file mode 100644 index 0000000..5f7220f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/editors/9999.rst.txt @@ -0,0 +1,33 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.9999 +--------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.80.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Textarea: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..2dac627 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Textarea: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/implementationClassName.rst.txt new file mode 100644 index 0000000..231ac7f --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Textarea: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..3d9bddc --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Textarea: + properties: + containerClassAttribute: input + elementClassAttribute: xxlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..ddf7b91 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Textarea: + properties: + containerClassAttribute: input + elementClassAttribute: xxlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementDescription.rst.txt new file mode 100644 index 0000000..8e173ca --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..ee71162 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Textarea/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Textarea.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Textarea: + properties: + containerClassAttribute: input + elementClassAttribute: xxlarge + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url.rst b/Documentation/I/Config/proto/formElements/formElementTypes/Url.rst new file mode 100644 index 0000000..16c823b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url.rst @@ -0,0 +1,88 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url: + +===== +[Url] +===== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.implementationclassname: +.. include:: Url/implementationClassName.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.properties.containerclassattribute: +.. include:: Url/properties/containerClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.properties.elementclassattribute: +.. include:: Url/properties/elementClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.properties.elementDescription: +.. include:: Url/properties/elementDescription.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.properties.elementerrorclassattribute: +.. include:: Url/properties/elementErrorClassAttribute.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.validators: +.. include:: Url/validators.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor: +.. include:: Url/formEditor.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.100: +.. include:: Url/formEditor/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.200: +.. include:: Url/formEditor/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.230: +.. include:: Url/formEditor/editors/230.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.400: +.. include:: Url/formEditor/editors/400.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.500: +.. include:: Url/formEditor/editors/500.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.700: +.. include:: Url/formEditor/editors/700.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.800: +.. include:: Url/formEditor/editors/800.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.900: +.. include:: Url/formEditor/editors/900.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.editors.9999: +.. include:: Url/formEditor/editors/9999.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.predefineddefaults: +.. include:: Url/formEditor/predefinedDefaults.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.propertycollections.validators.80: +.. include:: Url/formEditor/propertyCollections/validators/80.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.propertycollections.validators.80.identifier: +.. include:: Url/formEditor/propertyCollections/validators/80/identifier.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.propertycollections.validators.80.editors.100: +.. include:: Url/formEditor/propertyCollections/validators/80/editors/100.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.propertycollections.validators.80.editors.200: +.. include:: Url/formEditor/propertyCollections/validators/80/editors/200.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.label: +.. include:: Url/formEditor/label.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.group: +.. include:: Url/formEditor/group.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.groupsorting: +.. include:: Url/formEditor/groupSorting.rst.txt + +.. _prototypes.prototypeIdentifier.formelementsdefinition.url.formeditor.iconidentifier: +.. include:: Url/formEditor/iconIdentifier.rst.txt diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor.rst.txt new file mode 100644 index 0000000..88b7de9 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor.rst.txt @@ -0,0 +1,110 @@ +.. include:: /Includes.rst.txt +formEditor +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2- + + Url: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + doNotSetIfPropertyValueIsEmpty: true + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + label: formEditor.elements.Url.label + group: html5 + groupSorting: 300 + iconIdentifier: form-url diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/100.rst.txt new file mode 100644 index 0000000..92a8ad8 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/100.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.100 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.100 + +:aspect:`Data type` + array/ :ref:`[FormElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/200.rst.txt new file mode 100644 index 0000000..3b15876 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/200.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.200 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 200: + identifier: label + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/230.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/230.rst.txt new file mode 100644 index 0000000..f1e6212 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/230.rst.txt @@ -0,0 +1,29 @@ +.. include:: /Includes.rst.txt +formEditor.editors.230 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.230 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Date: + formEditor: + editors: + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/400.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/400.rst.txt new file mode 100644 index 0000000..39f4978 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/400.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.400 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.400 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 400: + identifier: placeholder + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.placeholder.label + propertyPath: properties.fluidAdditionalAttributes.placeholder + compatibilityPropertyPath: properties.placeholder + doNotSetIfPropertyValueIsEmpty: true + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/500.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/500.rst.txt new file mode 100644 index 0000000..b1a96d6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/500.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.500 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.500 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 500: + identifier: defaultValue + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.editor.defaultValue.label + propertyPath: defaultValue + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/700.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/700.rst.txt new file mode 100644 index 0000000..eaca620 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/700.rst.txt @@ -0,0 +1,51 @@ +.. include:: /Includes.rst.txt +formEditor.editors.700 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.700 + +:aspect:`Data type` + array/ :ref:`[GridColumnViewPortConfigurationEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/800.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/800.rst.txt new file mode 100644 index 0000000..bec34b2 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/800.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.800 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.800 + +:aspect:`Data type` + array/ :ref:`[RequiredValidatorEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/900.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/900.rst.txt new file mode 100644 index 0000000..74c171c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/900.rst.txt @@ -0,0 +1,37 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.900 +---------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.900 + +:aspect:`Data type` + array/ :ref:`[ValidatorsEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 900: + identifier: validators + templateName: Inspector-ValidatorsEditor + label: formEditor.elements.TextMixin.editor.validators.label + selectOptions: + 10: + value: '' + label: formEditor.elements.TextMixin.editor.validators.EmptyValue.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/9999.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/9999.rst.txt new file mode 100644 index 0000000..73bbf06 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/editors/9999.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + +formEditor.editors.9999 +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.editors.9999 + +:aspect:`Data type` + array/ :ref:`[RemoveElementEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +.. :aspect:`Related options` + @ToDo + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4- + + Url: + formEditor: + editors: + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/group.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/group.rst.txt new file mode 100644 index 0000000..4053af6 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/group.rst.txt @@ -0,0 +1,28 @@ +.. include:: /Includes.rst.txt +formEditor.group +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.group + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Url: + formEditor: + group: html5 + +:aspect:`Description` + Define within which group within the ``form editor`` "new Element" modal the form element should be shown. + The ``group`` value must be equal to an array key within ``formElementGroups``. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/groupSorting.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/groupSorting.rst.txt new file mode 100644 index 0000000..3203940 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/groupSorting.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.groupSorting +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.groupSorting + +:aspect:`Data type` + int + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Url: + formEditor: + groupSorting: 300 + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + The position within the ``formEditor.group`` for this form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/iconIdentifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/iconIdentifier.rst.txt new file mode 100644 index 0000000..549a84b --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/iconIdentifier.rst.txt @@ -0,0 +1,36 @@ +.. include:: /Includes.rst.txt +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Url: + formEditor: + iconIdentifier: form-url + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. + This icon will be shown within + + - :ref:`"Inspector [FormElementHeaderEditor]"`. + - :ref:`"Abstract view formelement templates"`. + - ``Tree`` component. + - "new element" Modal diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/label.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/label.rst.txt new file mode 100644 index 0000000..4be5595 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/label.rst.txt @@ -0,0 +1,30 @@ +.. include:: /Includes.rst.txt +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Url: + formEditor: + label: formEditor.elements.Url.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + This label will be shown within the "new element" Modal. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/predefinedDefaults.rst.txt new file mode 100644 index 0000000..e7d2bf7 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/predefinedDefaults.rst.txt @@ -0,0 +1,31 @@ +.. include:: /Includes.rst.txt +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Url: + formEditor: + predefinedDefaults: + defaultValue: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Defines predefined defaults for form element properties which are prefilled, if the form element is added to a form. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80.rst.txt new file mode 100644 index 0000000..a65b3c1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80.rst.txt @@ -0,0 +1,43 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80 +-------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.propertyCollections.validators.80 + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5- + + Url: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/100.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/100.rst.txt new file mode 100644 index 0000000..e7bdf3c --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/100.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.100 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Text.formEditor.propertyCollections.validators.80.editors.100 + +:aspect:`Data type` + array/ :ref:`[CollectionElementHeaderEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Text: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 100: + identifier: header + templateName: Inspector-CollectionElementHeaderEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.header.label + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/200.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/200.rst.txt new file mode 100644 index 0000000..9c2ea09 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/editors/200.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt + +formEditor.propertyCollections.validators.80.editors.200 +-------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.propertyCollections.validators.80.editors.200 + +:aspect:`Data type` + array/ :ref:`[TextEditor] ` + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 8- + + Url: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + editors: + 200: + identifier: regex + templateName: Inspector-TextEditor + label: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.label + description: formEditor.elements.TextMixin.validators.RegularExpression.editor.regex.description + propertyPath: options.regularExpression + propertyValidators: + 10: NotEmpty + 20: RegularExpressionPattern + diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/identifier.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/identifier.rst.txt new file mode 100644 index 0000000..b7780cf --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/formEditor/propertyCollections/validators/80/identifier.rst.txt @@ -0,0 +1,34 @@ +.. include:: /Includes.rst.txt +formEditor.propertyCollections.validators.80.identifier +------------------------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.formEditor.propertyCollections.validators.80.identifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 6 + + Url: + formEditor: + propertyCollections: + validators: + 80: + identifier: RegularExpression + +:aspect:`Good to know` + - :ref:`"Inspector"` + - :ref:`"\"` + +:aspect:`Description` + Identifies the validator which should be attached to the form element. Must be equal to an existing ````. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/implementationClassName.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/implementationClassName.rst.txt new file mode 100644 index 0000000..1e285a1 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/implementationClassName.rst.txt @@ -0,0 +1,35 @@ +.. include:: /Includes.rst.txt +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + No + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Url: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Classname which implements the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/containerClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/containerClassAttribute.rst.txt new file mode 100644 index 0000000..921dd35 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/containerClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.containerClassAttribute +---------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.properties.containerClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Url: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is typically wrapped around the form elements. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementClassAttribute.rst.txt new file mode 100644 index 0000000..48f6063 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementClassAttribute +-------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.properties.elementClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Url: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class written to the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementDescription.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementDescription.rst.txt new file mode 100644 index 0000000..3ee2dfa --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementDescription.rst.txt @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt +properties.elementDescription +----------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.properties.elementDescription + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`Form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + Undefined + +:aspect:`Good to know` + - :ref:`"Custom form element implementations"` + - :ref:`"Translate form definition"` + +:aspect:`Description` + Set a description of the form element. By default, it is displayed + below the form element. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementErrorClassAttribute.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementErrorClassAttribute.rst.txt new file mode 100644 index 0000000..f061fac --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/properties/elementErrorClassAttribute.rst.txt @@ -0,0 +1,38 @@ +.. include:: /Includes.rst.txt +properties.elementErrorClassAttribute +------------------------------------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.properties.elementErrorClassAttribute + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + No + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 5 + + Url: + properties: + containerClassAttribute: input + elementClassAttribute: '' + elementErrorClassAttribute: error + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + A CSS class which is written to the form element if validation errors exists. diff --git a/Documentation/I/Config/proto/formElements/formElementTypes/Url/validators.rst.txt b/Documentation/I/Config/proto/formElements/formElementTypes/Url/validators.rst.txt new file mode 100644 index 0000000..a781964 --- /dev/null +++ b/Documentation/I/Config/proto/formElements/formElementTypes/Url/validators.rst.txt @@ -0,0 +1,39 @@ +.. include:: /Includes.rst.txt +validators +---------- + +:aspect:`Option path` + prototypes..formElementsDefinition.Url.validators + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Overwritable within form definition` + Yes + +:aspect:`form editor can write this property into the form definition (for prototype 'standard')` + Yes + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Url: + validators: + - + identifier: RegularExpression + options: + regularExpression: '/^.*$/' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Predefined validators. diff --git a/Documentation/I/Config/proto/formEngine/Index.rst b/Documentation/I/Config/proto/formEngine/Index.rst new file mode 100644 index 0000000..d82c8e5 --- /dev/null +++ b/Documentation/I/Config/proto/formEngine/Index.rst @@ -0,0 +1,46 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.formengine: + +============ +[formEngine] +============ + + +.. _prototypes.prototypeIdentifier.formengine-properties: + +Properties +========== + +.. _prototypes.prototypeIdentifier.formengine.translationfiles: + +translationFiles +---------------- + +:aspect:`Option path` + prototypes..formEngine.translationFiles + +:aspect:`Data type` + string/ array + +:aspect:`Needed by` + Backend (plugin) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + formEngine: + translationFiles: + 10: 'EXT:form/Resources/Private/Language/Database.xlf' + +:aspect:`Good to know` + - :ref:`"Translate form plugin settings"` + +:aspect:`Description` + Filesystem path(s) to translation files which should be searched for form plugin translations. diff --git a/Documentation/I/Config/proto/validatorsDefinition/Index.rst b/Documentation/I/Config/proto/validatorsDefinition/Index.rst new file mode 100644 index 0000000..00bfe69 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/Index.rst @@ -0,0 +1,297 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition: + +====================== +[validatorsDefinition] +====================== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition-properties-validatorsdefinition: + +[validatorsDefinition] +---------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + .. code-block:: yaml + :linenos: + + prototypes: + : + validatorsDefinition: + [...] + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + Array which defines the available serverside validators. Every key within this array is called the ````. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier: + + +--------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition. + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + + prototypes: + standard: + NotEmpty: + [...] + DateTime: + [...] + Alphanumeric: + [...] + Text: + [...] + StringLength: + [...] + EmailAddress: + [...] + Integer: + [...] + Float: + [...] + NumberRange: + [...] + RegularExpression: + [...] + Count: + [...] + FileSize: + [...] + +:aspect:`Related options` + - :ref:`"prototypes.prototypeIdentifier.formElementsDefinition.formelementtypeidentifier.formEditor.propertyCollections.validators.[*].identifier"` + - :ref:`"[ValidatorsEditor] selectOptions.[*].value"` + - :ref:`"[RequiredValidatorEditor] validatorIdentifier"` + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + This array key identifies a validator. This identifier could be used to attach a validator to a form element. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier-commonproperties: + +Common properties +======================================= + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition..implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.options: + +options +------- + +:aspect:`Option path` + prototypes..validatorsDefinition..options + +:aspect:`Data type` + array + +:aspect:`Needed by` + Frontend/ Backend (form editor) + +:aspect:`Mandatory` + Depends (see :ref:`concrete validators configuration `) + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + Array with validator options. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.formeditor: + +formEditor +---------- + +:aspect:`Option path` + prototypes..validatorsDefinition..formEditor + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Recommended + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + Array with configurations for the ``form editor`` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.formeditor.iconidentifier: + +formeditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition..formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.formeditor.label: + +formeditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition..formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier.formeditor.predefineddefaults: + +formeditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition..formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value` + Depends (see :ref:`concrete validators configuration `) + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: properties/predefinedDefaults.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.validatoridentifier-concreteconfigurations: + +Concrete configurations +======================= + +.. toctree:: + + validators/Alphanumeric + validators/Count + validators/DateRange + validators/DateTime + validators/EmailAddress + validators/FileSize + validators/Float + validators/Integer + validators/NotEmpty + validators/Number + validators/NumberRange + validators/RegularExpression + validators/StringLength + validators/Text diff --git a/Documentation/I/Config/proto/validatorsDefinition/properties/iconIdentifier.rst.txt b/Documentation/I/Config/proto/validatorsDefinition/properties/iconIdentifier.rst.txt new file mode 100644 index 0000000..852ef1a --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/properties/iconIdentifier.rst.txt @@ -0,0 +1,4 @@ + + +An icon identifier which must be registered through the :php:`\TYPO3\CMS\Core\Imaging\IconRegistry`. +This icon will be shown within the - :ref:`"Inspector [CollectionElementHeaderEditor]"` if the validator is selected. diff --git a/Documentation/I/Config/proto/validatorsDefinition/properties/implementationClassName.rst.txt b/Documentation/I/Config/proto/validatorsDefinition/properties/implementationClassName.rst.txt new file mode 100644 index 0000000..0ffd182 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/properties/implementationClassName.rst.txt @@ -0,0 +1,3 @@ + + +Classname which implements the validator. diff --git a/Documentation/I/Config/proto/validatorsDefinition/properties/label.rst.txt b/Documentation/I/Config/proto/validatorsDefinition/properties/label.rst.txt new file mode 100644 index 0000000..06b681f --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/properties/label.rst.txt @@ -0,0 +1,3 @@ + + +This label will be shown within the - :ref:`"Inspector [CollectionElementHeaderEditor]"` if the validator is selected. diff --git a/Documentation/I/Config/proto/validatorsDefinition/properties/predefinedDefaults.rst.txt b/Documentation/I/Config/proto/validatorsDefinition/properties/predefinedDefaults.rst.txt new file mode 100644 index 0000000..394da22 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/properties/predefinedDefaults.rst.txt @@ -0,0 +1,3 @@ + + +Defines predefined defaults for validator options which are prefilled, if the validator is added to a form element. diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Alphanumeric.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Alphanumeric.rst new file mode 100644 index 0000000..7ef8202 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Alphanumeric.rst @@ -0,0 +1,123 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric: + +============== +[Alphanumeric] +============== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221551320` +- Error message: `The given subject was not a valid alphanumeric string.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Alphanumeric.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Alphanumeric: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\AlphanumericValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Alphanumeric.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Alphanumeric: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.alphanumeric.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Alphanumeric.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Alphanumeric: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Alphanumeric.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Count.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Count.rst new file mode 100644 index 0000000..ae00d48 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Count.rst @@ -0,0 +1,210 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count: + +======= +[Count] +======= + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1475002976` +- Error message: `You must enter a countable subject.` + +- Error code: `1475002994` +- Error message: `You must select between %s to %s elements.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Count: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\CountValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.options.minimum: + +options.minimum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.options.minimum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The minimum count to accept. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.options.maximum: + +options.maximum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.options.maximum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The maximum count to accept. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Count: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Count: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.MultiSelectionMixin.validators.Count.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.count.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Count.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + Count: + formEditor: + predefinedDefaults: + options: + minimum: '' + maximum: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/DateRange.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/DateRange.rst new file mode 100644 index 0000000..fd5f5a4 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/DateRange.rst @@ -0,0 +1,242 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange: + +=========== +[DateRange] +=========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1521293685` +- Error message: `You must enter an instance of \DateTime.` + +- Error code: `1521293686` +- Error message: `You must select a date before %s.` + +- Error code: `1521293687` +- Error message: `You must select a date after %s.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Count: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\DateRangeValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.options.format: + +options.format +-------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.options.format + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + + DateRange: + options: + format: Y-m-d + +:aspect:`Description` + The format of the minimum and maximum option. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.options.minimum: + +options.minimum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.options.minimum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The minimum date formatted as Y-m-d. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.options.maximum: + +options.maximum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.options.maximum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The maximum date formatted as Y-m-d. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + DateRange: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.validators.DateRange.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + DateRange: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.validators.DateRange.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.daterange.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateRange.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + DateRange: + formEditor: + predefinedDefaults: + options: + minimum: '' + maximum: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/DateTime.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/DateTime.rst new file mode 100644 index 0000000..feed5ce --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/DateTime.rst @@ -0,0 +1,123 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime: + +========== +[DateTime] +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime-validationerrorcodes: + +validation error codes +====================== + +- Error code: `1238087674` +- Error message: `The given subject was not a valid DateTime. Got: '%s'` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateTime.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + DateTime: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\DateTimeValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateTime.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + DateTime: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.DatePicker.validators.DateTime.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.datetime.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.DateTime.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + DateTime: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.DatePicker.validators.DateTime.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/EmailAddress.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/EmailAddress.rst new file mode 100644 index 0000000..5a89788 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/EmailAddress.rst @@ -0,0 +1,126 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress: + +============== +[EmailAddress] +============== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221559976` +- Error message: `The given subject was not a valid email address.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.EmailAddress.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + EmailAddress: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.EmailAddress.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + EmailAddress: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.emailaddress.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.EmailAddress.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + EmailAddress: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.EmailAddress.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/FileSize.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/FileSize.rst new file mode 100644 index 0000000..357e49c --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/FileSize.rst @@ -0,0 +1,211 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize: + +========== +[FileSize] +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1505303626` +- Error message: `You must enter an instance of \TYPO3\CMS\Extbase\Domain\Model\FileReference + or \TYPO3\CMS\Core\Resource\File.` + +- Error code: `1505305752` +- Error message: `You must select a file that is larger than %s in size.` + +- Error code: `1505305753` +- Error message: `You must select a file that is no larger than %s.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + FileSize: + implementationClassName: TYPO3\CMS\Form\Mvc\Validation\FileSizeValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.options.minimum: + +options.minimum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.options.minimum + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The minimum filesize to accept. Use the format `B|K|M|G`. For example: `10M` means 10 Megabytes. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.options.maximum: + +options.maximum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.options.maximum + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The maximum filesize to accept. Use the format `B|K|M|G`. For example: `10M` means 10 Megabytes. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + FileSize: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + FileSize: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FileUploadMixin.validators.FileSize.editor.header.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.filesize.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.FileSize.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + FileSize: + formEditor: + predefinedDefaults: + options: + minimum: '0B' + maximum: '10M' + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Float.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Float.rst new file mode 100644 index 0000000..fb6184c --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Float.rst @@ -0,0 +1,123 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float: + +======= +[Float] +======= + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221560288` +- Error message: `The given subject was not a valid float.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Float.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Float: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\FloatValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Float.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Float: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Float.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.float.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Float.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Float: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Float.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Integer.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Integer.rst new file mode 100644 index 0000000..a25e3f8 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Integer.rst @@ -0,0 +1,123 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer: + +========= +[Integer] +========= + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221560494` +- Error message: `The given subject was not a valid integer.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Integer.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Integer: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\IntegerValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Integer.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Integer: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Integer.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.integer.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Integer.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Integer: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Integer.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/NotEmpty.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/NotEmpty.rst new file mode 100644 index 0000000..a7b01ff --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/NotEmpty.rst @@ -0,0 +1,132 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty: + +========== +[NotEmpty] +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221560910` +- Error message: `The given subject was NULL.` + +- Error code: `1221560718` +- Error message: `The given subject was empty.` + +- Error code: `1347992400` +- Error message: `The given subject was empty.` + +- Error code: `1347992453` +- Error message: `The given subject was empty.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NotEmpty.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + NotEmpty: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NotEmptyValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NotEmpty.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + NotEmpty: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.editor.requiredValidator.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.notempty.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NotEmpty.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + NotEmpty: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.FormElement.editor.requiredValidator.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Number.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Number.rst new file mode 100644 index 0000000..eb7fb1c --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Number.rst @@ -0,0 +1,124 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number: + +======== +[Number] +======== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221563685` +- Error message: `The given subject was not a valid number.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Number.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Number: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NumberValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Number.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Number: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Number.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.number.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Number.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Number: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Number.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/NumberRange.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/NumberRange.rst new file mode 100644 index 0000000..a954814 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/NumberRange.rst @@ -0,0 +1,210 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange: + +============= +[NumberRange] +============= + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221563685` +- Error message: `The given subject was not a valid number.` + +- Error code: `1221561046` +- Error message: `The given subject was not in the valid range (%s - %s).` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + NumberRange: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\NumberRangeValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.options.minimum: + +options.minimum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.options.minimum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The minimum value to accept. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.options.maximum: + +options.maximum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.options.maximum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The maximum value to accept. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + NumberRange: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + NumberRange: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.NumberRange.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.numberrange.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.NumberRange.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + NumberRange: + formEditor: + predefinedDefaults: + options: + minimum: '' + maximum: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/RegularExpression.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/RegularExpression.rst new file mode 100644 index 0000000..94694ce --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/RegularExpression.rst @@ -0,0 +1,182 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression: + +=================== +[RegularExpression] +=================== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221565130` +- Error message: `The given subject did not match the pattern.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.RegularExpression.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + RegularExpression: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\RegularExpressionValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression.options.regularExpression: + +options.regularExpression +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.RegularExpression.options.regularExpression + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + The regular expression to use for validation, used as given. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.RegularExpression.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + RegularExpression: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.RegularExpression.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.RegularExpression.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + RegularExpression: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.RegularExpression.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.regularexpression.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.RegularExpression.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + RegularExpression: + formEditor: + predefinedDefaults: + options: + regularExpression: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/StringLength.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/StringLength.rst new file mode 100644 index 0000000..213c5e0 --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/StringLength.rst @@ -0,0 +1,219 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength: + +============== +[StringLength] +============== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1238110957` +- Error message: `The given object could not be converted to a string.` + +- Error code: `1269883975` +- Error message: `The given value was not a valid string.` + +- Error code: `1428504122` +- Error message: `The length of the given string was not between %s and %s characters.` + +- Error code: `1238108068` +- Error message: `The length of the given string is less than %s characters.` + +- Error code: `1238108069` +- Error message: `The length of the given string exceeded %s characters.` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + StringLength: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\StringLengthValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.options.minimum: + +options.minimum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.options.minimum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + Minimum length for a valid string. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.options.maximum: + +options.maximum +--------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.options.maximum + +:aspect:`Data type` + int + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + undefined + +:aspect:`Description` + Maximum length for a valid string. + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + StringLength: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + StringLength: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.StringLength.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.stringlength.formeditor.predefineddefaults: + +formEditor.predefinedDefaults +----------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.StringLength.formEditor.predefinedDefaults + +:aspect:`Data type` + array + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + No + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3- + + StringLength: + formEditor: + predefinedDefaults: + options: + minimum: '' + maximum: '' + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/predefinedDefaults.rst.txt diff --git a/Documentation/I/Config/proto/validatorsDefinition/validators/Text.rst b/Documentation/I/Config/proto/validatorsDefinition/validators/Text.rst new file mode 100644 index 0000000..88917cf --- /dev/null +++ b/Documentation/I/Config/proto/validatorsDefinition/validators/Text.rst @@ -0,0 +1,123 @@ +.. include:: /Includes.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text: + +====== +[Text] +====== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text-validationerrorcodes: + +Validation error codes +====================== + +- Error code: `1221565786` +- Error message: `The given subject was not a valid text (e.g. contained XML tags).` + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text-properties: + +Properties +========== + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text.implementationClassName: + +implementationClassName +----------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Text.implementationClassName + +:aspect:`Data type` + string + +:aspect:`Needed by` + Frontend + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 2 + + Text: + implementationClassName: TYPO3\CMS\Extbase\Validation\Validator\TextValidator + +:aspect:`Good to know` + - :ref:`"Custom validator implementations"` + +:aspect:`Description` + .. include:: ../properties/implementationClassName.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text.formeditor.iconidentifier: + +formEditor.iconIdentifier +------------------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Text.formEditor.iconIdentifier + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 3 + + Text: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Text.label + +.. :aspect:`Good to know` + ToDo + +:aspect:`Description` + .. include:: ../properties/iconIdentifier.rst.txt + + +.. _prototypes.prototypeIdentifier.validatorsdefinition.text.formeditor.label: + +formEditor.label +---------------- + +:aspect:`Option path` + prototypes..validatorsDefinition.Text.formEditor.label + +:aspect:`Data type` + string + +:aspect:`Needed by` + Backend (form editor) + +:aspect:`Mandatory` + Yes + +:aspect:`Default value (for prototype 'standard')` + .. code-block:: yaml + :linenos: + :emphasize-lines: 4 + + Text: + formEditor: + iconIdentifier: form-validator + label: formEditor.elements.TextMixin.editor.validators.Text.label + +:aspect:`Good to know` + - :ref:`"Translate form editor settings"` + +:aspect:`Description` + .. include:: ../properties/label.rst.txt diff --git a/Documentation/I/FAQ/Index.rst b/Documentation/I/FAQ/Index.rst new file mode 100644 index 0000000..4de27f9 --- /dev/null +++ b/Documentation/I/FAQ/Index.rst @@ -0,0 +1,248 @@ +.. include:: /Includes.rst.txt + + +.. _faq: + +=== +FAQ +=== + + +.. _faq-override-frontend-templates: + +How do I override EXT:Form frontend templates? +============================================== + +There are three ways to override the frontend templates. + + +Override template paths via site set settings (recommended) +----------------------------------------------------------- + +The simplest approach: configure the template paths in the site settings of +your site package. The settings are applied to the Extbase plugin view and +the form element rendering. + +.. code-block:: yaml + :caption: config/sites/my-site/settings.yaml + + form.templates.templateRootPath: EXT:my_site_package/Resources/Private/Templates/Form/Frontend/ + form.templates.partialRootPath: EXT:my_site_package/Resources/Private/Partials/Form/Frontend/ + form.templates.layoutRootPath: EXT:my_site_package/Resources/Private/Layouts/Form/Frontend/ + form.translation.translationFile: EXT:my_site_package/Resources/Private/Language/Form/locallang.xlf + +Alternatively, edit the settings in the :guilabel:`Site Settings` backend +module under :guilabel:`Form Framework > Templates`. + +.. note:: + + Site set settings are resolved in the **frontend** only. The backend form + editor preview uses the YAML prototype defaults. If you need the backend + preview to use custom templates, use a form set (see below). + + +Add fluid search paths via a form set +------------------------------------- + +Create a form set in your site package. The YAML files are picked up +automatically for **both** frontend and backend — no PHP or TypoScript +registration is required. + +1. Create the directory and a :file:`config.yaml` with the template paths: + + .. code-block:: none + + EXT:my_site_package/ + Configuration/ + Form/ + SitePackage/ + config.yaml + + .. code-block:: yaml + :caption: EXT:my_site_package/Configuration/Form/SitePackage/config.yaml + + name: my-site-package/form + label: 'My Site Package — Form Configuration' + priority: 200 + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + templateRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Templates/Form/Frontend/' + partialRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Partials/Form/Frontend/' + layoutRootPaths: + 20: 'EXT:my_site_package/Resources/Private/Layouts/Form/Frontend/' + +.. note:: + + Forms can be previewed in the backend form editor. The preview uses the + same frontend templates. Your customized templates are automatically used + in the preview as well. + +See :ref:`concepts-configuration-yaml-autodiscovery` for the full directory +convention. + + +Add fluid search paths via TypoScript ``yamlSettingsOverrides`` +--------------------------------------------------------------- + +For quick, per-site overrides without creating a full form set, you can use +:typoscript:`plugin.tx_form.settings.yamlSettingsOverrides`: + +.. code-block:: typoscript + + plugin.tx_form.settings.yamlSettingsOverrides { + prototypes { + standard { + formElementsDefinition { + Form { + renderingOptions { + templateRootPaths { + 20 = EXT:my_site_package/Resources/Private/Templates/Form/Frontend/ + } + } + } + } + } + } + } + +.. note:: + + TypoScript ``yamlSettingsOverrides`` are evaluated in the **frontend only** + and are ignored by the backend form editor. + + +.. _faq-prevent-double-submissions: + +How do I prevent multiple form submissions? +=========================================== + +A user can submit a form twice by double-clicking the submit button. This means +finishers could be processed multiple times. + +At the current time, there are no plans to integrate a function to prevent this behaviour, +especially not server side. An easy solution would be the integration of a +JavaScript function to stop the behaviour. TYPO3 itself does not take care of +any frontend integration and does not want to ship JavaScript solutions for +the frontend. Therefore, integrators have to implement a solution themselves. + +One possible solution is the following JavaScript snippet. It can be added to your +site package. Please note, the selector (here :js:`myform-123`) has to be updated +to the id of your form. + +.. code-block:: js + + const form = document.getElementById('myform-123'); + form.addEventListener('submit', function(e) { + const submittedClass = 'submitted'; + if (this.classList.contains(submittedClass)) { + e.preventDefault(); + } else { + this.classList.add(submittedClass); + } + }); + +You could also style the submit button to provide visual feedback to the user. +This will help make it clear that the form has already been submitted and thus +prevent further interaction by the user. + +.. code-block:: css + + .submitted button[type="submit"] { + opacity: 0.6; + pointer-events: none; + } + + +.. _faq-user-registration: + +Is it possible to build frontend user registration with EXT:form? +================================================================= + +Possible, yes. But we are not aware of an implementation. + + +.. _faq-export-module: + +Is there an export module for saved forms? +========================================== + +Currently there are no plans to implement such a feature in the core. There +are concerns regarding data privacy when it comes to storing user data in +your TYPO3 database permanently. The great folks of Pagemachine created an +`extension `_ for this. + + +.. _faq-honeypt-session: + +The honeypot does not work with static site caching. What can I do? +=================================================================== + +If you want to use static site caching - for example using the +staticfilecache extension - you should disable the automatic inclusion of the +honeypot. Read more :ref:`here`. + + +.. _faq-form-element-default-value: + +How do I set a default value for my form element? +================================================= + +You can set default values for most form elements (not to be confused with +the placeholder attribute). This is easy for text fields and textareas. + +Select and multi-select form elements are a bit more complex. These form elements +can have :yaml:`defaultValue` and :yaml:`prependOptionValue` settings. The +:yaml:`defaultValue` allows you to select a specific option as a default. This +option will be pre-selected when the +form is loaded. The :yaml:`prependOptionValue` defines a +string which will be the first select option. If both settings exist, +the :yaml:`defaultValue` is prioritized. + +Learn more :ref:`here` +and see forge issue `#82422 `_. + + +.. _faq-form-element-custom-finisher: + +How do I create a custom finisher for my form? +============================================== + +:ref:`Learn how to create a custom finisher here.` + +If you want to make the finisher configurable in the backend form editor, read :ref:`here`. + + +.. _faq-form-element-custom-validator: + +How do I create a custom validator for my form? +=============================================== + +:ref:`Learn how to create a custom validator here.` + + +.. faq-form-proposed-folder-structure: + +Which folder structure do you recommend? +======================================== + +When shipping form configuration, form definitions, +form templates, and language files in a site package, we recommend the following +structure: + +* Form configuration: :file:`EXT:my_site_package/Configuration/Form/` +* Form definitions: :file:`EXT:my_site_package/Resources/Private/Forms/` +* Form templates: + * Templates :file:`EXT:my_site_package/Resources/Private/Templates/Form/` + * Partials :file:`EXT:my_site_package/Resources/Private/Partials/Form/` + * Layouts :file:`EXT:my_site_package/Resources/Private/Layouts/Form/` + * Keep in mind that a form comes with templates for both the frontend + (this is your website) and the TYPO3 backend. Therefore, we recommend + splitting the templates into subfolders called :file:`Frontend/` and + :file:`Backend/`. +* Translations: :file:`EXT:my_site_package/Resources/Private/Language/Form/` diff --git a/Documentation/I/HowTos/CustomFormElement/Index.rst b/Documentation/I/HowTos/CustomFormElement/Index.rst new file mode 100644 index 0000000..eae4788 --- /dev/null +++ b/Documentation/I/HowTos/CustomFormElement/Index.rst @@ -0,0 +1,173 @@ +.. include:: /Includes.rst.txt + +.. _howtos-custom-form-element: + +============================== +Creating a custom form element +============================== + +This tutorial shows you how to create a custom form element for the TYPO3 Form +Framework. We'll create a "Gender Select" element as an example. + +.. contents:: Table of Contents + :depth: 2 + :local: + +Prerequisites +============= + +Before you start, make sure you have: + +* Basic knowledge of YAML configuration +* A sitepackage where you can add configuration files + +Step 1: Create the configuration files +====================================== + +Create a form set directory in your extension. The sub-directory name is +arbitrary — we use ``CustomElement`` here. + +File location +------------- + +Create the following structure in your extension: + +.. code-block:: none + + EXT:my_extension/ + Configuration/ + Form/ + CustomElement/ + config.yaml + +Configuration structure +----------------------- + +Here's the complete configuration for our Gender Select element: + +.. literalinclude:: _CustomFormSetup.yaml + :language: yaml + :caption: EXT:my_extension/Configuration/Form/CustomElement/config.yaml (after metadata) + +Common inspector editors +~~~~~~~~~~~~~~~~~~~~~~~~ + +Here are some commonly used inspector editors (:ref:`Inspector `) you can add to your form elements: + +**Inspector-FormElementHeaderEditor** (100) + Shows the element header in the inspector panel + +**Inspector-TextEditor** (200-300) + A simple text input field for properties like label and description + +**Inspector-PropertyGridEditor** (400) + A grid editor for managing key-value pairs (like options) + +**Inspector-GridColumnViewPortConfigurationEditor** (700) + Controls responsive behavior and column widths for different screen sizes + +**Inspector-RequiredValidatorEditor** (800) + Adds a checkbox to make the field required + +**Inspector-ValidationErrorMessageEditor** (900) + Allows customizing validation error messages + +**Inspector-RemoveElementEditor** (9999) + Shows a button to remove the element from the form + +Step 2: Register the configuration +=================================== + +No PHP or TypoScript registration is needed. TYPO3 discovers YAML files +automatically from any extension that follows the directory convention. + +Create a form set with a single :file:`config.yaml`: + +.. code-block:: none + + EXT:my_extension/ + Configuration/ + Form/ + CustomElement/ + config.yaml ← set metadata + all configuration + +Set the ``priority`` in :file:`config.yaml` to a value greater than ``10`` +(the EXT:form core base set) so your configuration is merged on top: + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Form/CustomElement/config.yaml + + name: my-vendor/custom-element + label: 'My Custom Form Element' + priority: 200 + + # Form element configuration goes here: + prototypes: + standard: + ... + +Step 3: Clear Caches +==================== + +After adding the configuration, you must clear all TYPO3 caches. + +Step 4: Using your custom element +================================== + +Now you can use your custom element in the form editor: + +1. Open the Form Editor user interface (:guilabel:`Forms > [Your Form] > Edit`) +2. Look for "Gender Select" in the form element browser. +3. Add the element to the form. +4. Configure the element using the inspector panel on the right. +5. Save your form. +6. Add a form content element to a page and select the form you just edited. +7. Preview the page in the frontend. + +The element will now be available in your forms and will render using the +RadioButton template in the frontend. + +Step 5: Customizing frontend output (optional) +=============================================== + +If you want to use a custom template instead of reusing an existing one, follow +these steps: + +Create custom template +---------------------- + +Create your own Fluid template: + +:file:`EXT:my_extension/Resources/Private/Partials/Form/GenderSelect.fluid.html` + +.. literalinclude:: _GenderSelect.fluid.html + :language: html + :caption: EXT:my_extension/Resources/Private/Partials/Form/GenderSelect.fluid.html + + +Update configuration +-------------------- + +Update your YAML configuration to use the custom partial template: + +.. code-block:: yaml + :caption: EXT:my_extension/Configuration/Form/CustomElement/config.yaml + :emphasize-lines: 3-7, 10 + + prototypes: + standard: + formElementsDefinition: + Form: + renderingOptions: + partialRootPaths: + 1732785721: 'EXT:my_extension/Resources/Private/Partials/Form/' + GenderSelect: + renderingOptions: + templateName: 'GenderSelect' + + +Further reading +=============== + +* :ref:`Form Configuration ` +* :ref:`Register a custom stage template ` \ No newline at end of file diff --git a/Documentation/I/HowTos/CustomFormElement/_CustomFormSetup.yaml b/Documentation/I/HowTos/CustomFormElement/_CustomFormSetup.yaml new file mode 100644 index 0000000..12c0ec2 --- /dev/null +++ b/Documentation/I/HowTos/CustomFormElement/_CustomFormSetup.yaml @@ -0,0 +1,82 @@ +prototypes: + standard: + formElementsDefinition: + GenderSelect: + implementationClassName: TYPO3\CMS\Form\Domain\Model\FormElements\GenericFormElement + renderingOptions: + templateName: 'RadioButton' + properties: + options: + f: 'Female' + m: 'Male' + d: 'Diverse' + formEditor: + label: 'Gender Select' + group: select + groupSorting: 9000 + iconIdentifier: form-single-select + editors: + 100: + identifier: header + templateName: Inspector-FormElementHeaderEditor + 200: + identifier: label + templateName: Inspector-TextEditor + # Labels are retrieved from the default language file "EXT:form/Resources/Private/Language/Database.xlf" + # The most keys follow the pattern: formEditor.elements.FormElement.editor.[identifier].[key] + # In this example: "formEditor.elements.FormElement.editor.label.label" + label: formEditor.elements.FormElement.editor.label.label + propertyPath: label + 230: + identifier: elementDescription + templateName: Inspector-TextEditor + label: formEditor.elements.FormElement.editor.elementDescription.label + propertyPath: properties.elementDescription + 700: + identifier: gridColumnViewPortConfiguration + templateName: Inspector-GridColumnViewPortConfigurationEditor + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.label + configurationOptions: + viewPorts: + 10: + viewPortIdentifier: xs + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xs.label + 20: + viewPortIdentifier: sm + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.sm.label + 30: + viewPortIdentifier: md + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.md.label + 40: + viewPortIdentifier: lg + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.lg.label + 50: + viewPortIdentifier: xl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xl.label + 60: + viewPortIdentifier: xxl + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.xxl.label + numbersOfColumnsToUse: + label: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.label + propertyPath: 'properties.gridColumnClassAutoConfiguration.viewPorts.{@viewPortIdentifier}.numbersOfColumnsToUse' + description: formEditor.elements.FormElement.editor.gridColumnViewPortConfiguration.numbersOfColumnsToUse.description + 800: + identifier: requiredValidator + templateName: Inspector-RequiredValidatorEditor + label: formEditor.elements.FormElement.editor.requiredValidator.label + validatorIdentifier: NotEmpty + propertyPath: properties.fluidAdditionalAttributes.required + propertyValue: required + configurationOptions: + validationErrorMessage: + label: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.label + propertyPath: properties.validationErrorMessages + description: formEditor.elements.FormElement.editor.requiredValidator.validationErrorMessage.description + errorCodes: + 10: 1221560910 + 20: 1221560718 + 30: 1347992400 + 40: 1347992453 + 9999: + identifier: removeButton + templateName: Inspector-RemoveElementEditor diff --git a/Documentation/I/HowTos/CustomFormElement/_GenderSelect.fluid.html b/Documentation/I/HowTos/CustomFormElement/_GenderSelect.fluid.html new file mode 100644 index 0000000..cc3bcbb --- /dev/null +++ b/Documentation/I/HowTos/CustomFormElement/_GenderSelect.fluid.html @@ -0,0 +1,105 @@ + + + + Custom form element template for a gender selection field. + + + + + Render the field wrapper with optional fieldset and legend + + + + + Apply error class if validation errors exist + + {f:if( + condition: '{validationResults.errors}', + then: 'is-invalid' + )} + + + Radio button group container +
+ + Loop through all available options (e.g., male, female, diverse) + + + Set ARIA attributes for accessibility + + + + + Add error indication to the first radio button if validation fails + + + + + Individual radio button container +
+ +
+ +
+ +
+ + Display validation errors + + + + + + {formvh:translateElementError(element: element, error: error)} + +
+
+ +
+
+ +
+ +
+ +
+ + diff --git a/Documentation/I/HowTos/Index.rst b/Documentation/I/HowTos/Index.rst new file mode 100644 index 0000000..438934f --- /dev/null +++ b/Documentation/I/HowTos/Index.rst @@ -0,0 +1,16 @@ +.. include:: /Includes.rst.txt + +.. _howtos: + +======== +How-To's +======== + +This section provides step-by-step tutorials for common tasks when working +with the TYPO3 Form Framework. + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + CustomFormElement/Index diff --git a/Documentation/I/Images/basic_code_components.png b/Documentation/I/Images/basic_code_components.png new file mode 100644 index 0000000..7e6612f Binary files /dev/null and b/Documentation/I/Images/basic_code_components.png differ diff --git a/Documentation/I/Images/form_manager.png b/Documentation/I/Images/form_manager.png new file mode 100644 index 0000000..d2352c7 Binary files /dev/null and b/Documentation/I/Images/form_manager.png differ diff --git a/Documentation/I/Images/javascript_module_interaction.png b/Documentation/I/Images/javascript_module_interaction.png new file mode 100644 index 0000000..1b133d6 Binary files /dev/null and b/Documentation/I/Images/javascript_module_interaction.png differ diff --git a/Documentation/I/Index.rst b/Documentation/I/Index.rst new file mode 100644 index 0000000..ece52bc --- /dev/null +++ b/Documentation/I/Index.rst @@ -0,0 +1,16 @@ +.. include:: /Includes.rst.txt + + +.. _forIntegrators: + +=============== +For Integrators +=============== + +.. toctree:: + :maxdepth: 1 + + Concepts/Index + Config/Index + HowTos/Index + FAQ/Index diff --git a/Documentation/Images/InstallActivate.png b/Documentation/Images/InstallActivate.png new file mode 100644 index 0000000..af3214b Binary files /dev/null and b/Documentation/Images/InstallActivate.png differ diff --git a/Documentation/Images/SiteSet.png b/Documentation/Images/SiteSet.png new file mode 100644 index 0000000..5f00e72 Binary files /dev/null and b/Documentation/Images/SiteSet.png differ diff --git a/Documentation/Includes.rst.txt b/Documentation/Includes.rst.txt new file mode 100644 index 0000000..2362507 --- /dev/null +++ b/Documentation/Includes.rst.txt @@ -0,0 +1 @@ +.. You can put central messages to display on all pages here diff --git a/Documentation/Includes/_NoteFinisher.rst b/Documentation/Includes/_NoteFinisher.rst new file mode 100644 index 0000000..7d80571 --- /dev/null +++ b/Documentation/Includes/_NoteFinisher.rst @@ -0,0 +1,7 @@ +:orphan: + +.. important:: + + Finishers are executed in the order defined in your form definition. + + See `Finisher execution order `_. diff --git a/Documentation/Index.rst b/Documentation/Index.rst new file mode 100644 index 0000000..e3a52ea --- /dev/null +++ b/Documentation/Index.rst @@ -0,0 +1,56 @@ +.. include:: /Includes.rst.txt +.. _start: + +========== +TYPO3 Form +========== + +:Extension key: + form + +:Package name: + typo3/cms-form + +:Version: + |release| + +:Language: + en + +:Author: + TRITUM GmbH & TYPO3 contributors + +:License: + This document is published under the + `Open Content License `__. + +:Rendered: + |today| + +---- + +This is a flexible TYPO3 frontend form framework that allows editors, +integrators and developers alike to create all kinds of forms. + +---- + +**Table of Contents:** + +.. toctree:: + :maxdepth: 2 + :titlesonly: + + Introduction/Index + Installation/Index + QuickStartForEditors/Index + QuickStartForIntegrators/Index + D/Index + I/Index + E/Index + +.. Meta Menu + +.. toctree:: + :hidden: + + Sitemap diff --git a/Documentation/Installation/Index.rst b/Documentation/Installation/Index.rst new file mode 100644 index 0000000..17e0a23 --- /dev/null +++ b/Documentation/Installation/Index.rst @@ -0,0 +1,52 @@ +.. include:: /Includes.rst.txt + +.. _installation: + +============ +Installation +============ + +This extension is part of the TYPO3 Core, but not installed by default. + +.. contents:: Table of contents + :local: + +Installation with Composer +========================== + +Check whether you are already using the extension with: + +.. code-block:: bash + + composer show | grep form + +This should either give you no result or something similar to: + +.. code-block:: none + + typo3/cms-form v12.4.11 + +If it is not installed yet, use the ``composer require`` command to install +the extension: + +.. code-block:: bash + + composer require typo3/cms-form + +The given version depends on the version of the TYPO3 Core you are using. + +Installation without Composer +============================= + +In an installation without Composer, the extension is already shipped but might +not be activated yet. Activate it as follows: + +#. In the backend, navigate to the :guilabel:`System > Extensions` + module. +#. Click the :guilabel:`Activate` icon for the Form extension. + +.. figure:: /Images/InstallActivate.png + :class: with-border + :alt: Extension manager showing Form extension + + Extension manager showing Form extension diff --git a/Documentation/Introduction/Images/introduction_form_editor.png b/Documentation/Introduction/Images/introduction_form_editor.png new file mode 100644 index 0000000..6ed4716 Binary files /dev/null and b/Documentation/Introduction/Images/introduction_form_editor.png differ diff --git a/Documentation/Introduction/Index.rst b/Documentation/Introduction/Index.rst new file mode 100644 index 0000000..27d07f9 --- /dev/null +++ b/Documentation/Introduction/Index.rst @@ -0,0 +1,98 @@ +.. include:: /Includes.rst.txt + +.. _introduction: + +============ +Introduction +============ + +.. note:: + + This documentation will be extended on a constant basis. If you have + problems understanding a certain aspect or if you notice something + missing, please contribute to improve it. This will help you as well as everyone else! + + Get in touch with us: + + * Find us on `Slack `_ and join the + channel `#ext:form`. + * Use the "Edit on Github" function. + + +.. _what-does-it-do: + +What does it do? +================ + +The :composer:`typo3/cms-form` extension is a system extension that provides a +flexible, extendable, and easy-to-use form framework. It incorporates interfaces +and functionality that allow editors, integrators and developers to build forms. + +Non-technical editors can use the :guilabel:`Content > Forms` backend module. +They can create and manage forms using a simple drag and drop interface. +Forms can be previewed instantly. + +Experienced integrators can build ambitious forms which are +stored in a site package. These forms can use powerful finishers and ship +localization files. + +Developers can use the PHP API to create interfaces with conditional +form elements, register new validators and finishers, as well as create +custom form elements. Plenty of hooks allow form creation +and processing to be manipulated. + +.. figure:: Images/introduction_form_editor.png + :alt: The form creation wizard + + Form editor displaying a new form in the abstract view + +.. _features_list: + +Features list +============= + +Here are some of the features of the form framework: + +* form editor + + * fully customizable editor for building complex forms + * replaceable and extendable form editor components + * JS API to extend form editor + +* PHP API + + * entire forms via API + * own renderers for form and/ or form elements + * conditional steps, form elements and validators based on other form + elements + +* configuration + + * YAML as configuration and definition language including inheritance + and overrides + * file based + * behaviour and design of the frontend, plugin, and form editor can be + adapted for individual forms + * 'prototypes' can be used as boilerplate + +* form elements + + * own form elements possible + * uploads handled as FAL objects + +* finishers + + * ships built-in finishers, like email, redirect, and save-to-database + * own finishers possible + * finisher configuration can be overridden in the form plugin + +* validators + + * own validators possible + +* miscellaneous + + * multiple languages support + * multiple steps support + * multiple forms on one page + * built-in spam protection (honeypot) diff --git a/Documentation/QuickStartForEditors/Index.rst b/Documentation/QuickStartForEditors/Index.rst new file mode 100644 index 0000000..84fd1ec --- /dev/null +++ b/Documentation/QuickStartForEditors/Index.rst @@ -0,0 +1,32 @@ +.. include:: /Includes.rst.txt + + +.. _quickstartEditors: + +======================= +Quick Start for Editors +======================= + +Are you an editor, the form extension has already been installed by your admin and you want +to get started quickly? Follow these steps: + +.. rst-class:: bignums-xxl + +1. Create a new form + + Go to the ``Forms`` module and build a form using the form editor. With the + form editor you can quickly build appealing forms. + +2. Insert the form on a page + + The next step is inserting the form on the desired page(s). + + #. Open the page module in the backend. + #. Go to your desired page. + #. Create a new content element of type "Form". You can find this + under the "Form Elements" tab. + #. Select your form on the "Plugin" tab. + #. Save the form content element. + #. Repeat steps 2 to 5 to insert the form on further pages. + +View your form on your web site. Enjoy! diff --git a/Documentation/QuickStartForIntegrators/Index.rst b/Documentation/QuickStartForIntegrators/Index.rst new file mode 100644 index 0000000..011569e --- /dev/null +++ b/Documentation/QuickStartForIntegrators/Index.rst @@ -0,0 +1,76 @@ +.. include:: /Includes.rst.txt + +.. _quickstartIntegrators: + +=========================== +Quick Start for Integrators +=========================== + +Are you an integrator, you or your admin have already installed the form extension +and you want to get started quickly? Just follow these steps: + +.. rst-class:: bignums-xxl + +#. Include a site set + + .. versionadded:: 13.3 + EXT:form contains a site set that can be included as described here. + :ref:`quickstartIntegrators-typoscript-includes` are still possible + for compability reasons but not recommended anymore. + + Include the "Form Framework" site set in the :ref:`site + configuration ` or as a dependency in a custom + :ref:`site package `. + + .. figure:: /Images/SiteSet.png + + Add the site set "Form Framework" + +#. Create a new form + + Go to the ``Forms`` module and create a new form using the form editor. With + the form editor you can quickly build appealing forms. + +#. Move the form definition + + If required, :ref:`move the form definition into a dedicated + extension`. + +#. Provide a translation + + Create a + :ref:`translation` + of your form if required by registering the .xlf file in your YAML configuration. + +#. Insert your form on a page + + The final step is inserting the form on the desired page(s). + + #. Open the page module in the backend. + #. Go to the desired page. + #. Create a new content element of type "Form". You can find this + on the "Form Elements" tab. + #. Select your new form on the "Plugin" tab. + #. Select "Override finisher settings" on the + "Plugin" tab if necessary. Save the form content element. + #. Repeat steps 2 to 5 to insert the form on further pages. + +View your form in the frontend. Enjoy! + +.. _quickstartIntegrators-typoscript-includes: + +Legacy TypoScript includes +========================== + +.. versionchanged:: 13.3 + It is recommended to include the TypoScript via site set. The legacy way + of using TypoScript includes, in the past also called "TypoScript sets" + is still possible for compatibility reasons but not recommended anymore. + + +Open the ``TypoScript`` module in the backend and edit your root +TypoScript record. Under the tab "Includes", ensure that "Fluid Content +Elements" (`fluid_styled_content`) and "Form" (`form`) are among the selected +items. Save the record. + +Then continue with the steps above. diff --git a/Documentation/Sitemap.rst b/Documentation/Sitemap.rst new file mode 100644 index 0000000..09d3c6f --- /dev/null +++ b/Documentation/Sitemap.rst @@ -0,0 +1,9 @@ +:template: sitemap.html + +.. include:: /Includes.rst.txt + +======= +Sitemap +======= + +.. The sitemap.html template will insert here the page tree automatically. diff --git a/Documentation/guides.xml b/Documentation/guides.xml new file mode 100644 index 0000000..ee61d25 --- /dev/null +++ b/Documentation/guides.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..3639c79 --- /dev/null +++ b/README.rst @@ -0,0 +1,11 @@ +======================== +TYPO3 extension ``form`` +======================== + +This is a flexible TYPO3 frontend form framework that allows editors, +integrators and developers alike to create all kinds of forms. + +:Repository: https://github.com/typo3/typo3 +:Issues: https://forge.typo3.org/ +:Read online: https://docs.typo3.org/c/typo3/cms-form/main/en-us/ +:Packagist: https://packagist.org/packages/typo3/cms-form diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/CheckboxEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/CheckboxEditor.fluid.html new file mode 100644 index 0000000..468550e --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/CheckboxEditor.fluid.html @@ -0,0 +1,14 @@ + +
+
+ +
+
+ + +
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/CollectionElementHeaderEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/CollectionElementHeaderEditor.fluid.html new file mode 100644 index 0000000..ae3ca41 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/CollectionElementHeaderEditor.fluid.html @@ -0,0 +1,8 @@ + +

+
+
+
+
+

+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySelectEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySelectEditor.fluid.html new file mode 100644 index 0000000..0f41d9f --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySelectEditor.fluid.html @@ -0,0 +1,16 @@ + +
+
+ +
+
+
+ +
+
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySingleSelectEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySingleSelectEditor.fluid.html new file mode 100644 index 0000000..d887dc1 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/CountrySingleSelectEditor.fluid.html @@ -0,0 +1,16 @@ + +
+
+ +
+
+
+ +
+
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/DateEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/DateEditor.fluid.html new file mode 100644 index 0000000..bd72333 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/DateEditor.fluid.html @@ -0,0 +1,14 @@ + +
+
+ +
+
+ +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/FinishersEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/FinishersEditor.fluid.html new file mode 100644 index 0000000..e13d71c --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/FinishersEditor.fluid.html @@ -0,0 +1,16 @@ + +
+
+ +
+ +
+
+
+ +
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/FormElementHeaderEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/FormElementHeaderEditor.fluid.html new file mode 100644 index 0000000..0e135ba --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/FormElementHeaderEditor.fluid.html @@ -0,0 +1,5 @@ + +
+

+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/GridColumnViewPortConfigurationEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/GridColumnViewPortConfigurationEditor.fluid.html new file mode 100644 index 0000000..1bfbb4e --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/GridColumnViewPortConfigurationEditor.fluid.html @@ -0,0 +1,25 @@ + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/MaximumFileSizeEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/MaximumFileSizeEditor.fluid.html new file mode 100644 index 0000000..29276e8 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/MaximumFileSizeEditor.fluid.html @@ -0,0 +1,10 @@ + + +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/MultiSelectEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/MultiSelectEditor.fluid.html new file mode 100644 index 0000000..74980cf --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/MultiSelectEditor.fluid.html @@ -0,0 +1,16 @@ + +
+
+ +
+
+
+ +
+
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/PropertyGridEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/PropertyGridEditor.fluid.html new file mode 100644 index 0000000..b1dd48f --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/PropertyGridEditor.fluid.html @@ -0,0 +1,25 @@ + +
+
+ +
+
+ + + + +
+
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/RemoveElementEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/RemoveElementEditor.fluid.html new file mode 100644 index 0000000..ce26e9b --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/RemoveElementEditor.fluid.html @@ -0,0 +1,8 @@ + +
+ +
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/RequiredValidatorEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/RequiredValidatorEditor.fluid.html new file mode 100644 index 0000000..f5b8643 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/RequiredValidatorEditor.fluid.html @@ -0,0 +1,22 @@ + +
+
+ +
+ + +
+
+
+ +
+
+ +
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/SingleSelectEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/SingleSelectEditor.fluid.html new file mode 100644 index 0000000..e12ae36 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/SingleSelectEditor.fluid.html @@ -0,0 +1,16 @@ + +
+
+ +
+
+
+ +
+
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/TextEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/TextEditor.fluid.html new file mode 100644 index 0000000..b5b7d34 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/TextEditor.fluid.html @@ -0,0 +1,17 @@ + +
+
+ +
+
+
+ +
+ +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/TextareaEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/TextareaEditor.fluid.html new file mode 100644 index 0000000..5b6d4e2 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/TextareaEditor.fluid.html @@ -0,0 +1,14 @@ + +
+
+ +
+
+ +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/Typo3WinBrowserEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/Typo3WinBrowserEditor.fluid.html new file mode 100644 index 0000000..6065db8 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/Typo3WinBrowserEditor.fluid.html @@ -0,0 +1,21 @@ + +
+
+ +
+
+ + +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidationErrorMessageEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidationErrorMessageEditor.fluid.html new file mode 100644 index 0000000..7f4faee --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidationErrorMessageEditor.fluid.html @@ -0,0 +1,15 @@ + +
+
+ +
+
+
+ +
+
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidatorsEditor.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidatorsEditor.fluid.html new file mode 100644 index 0000000..cefe929 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Inspector/ValidatorsEditor.fluid.html @@ -0,0 +1,18 @@ + +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ diff --git a/Resources/Private/Backend/Partials/FormEditor/Modals/InsertElements.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Modals/InsertElements.fluid.html new file mode 100644 index 0000000..e3dd87b --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Modals/InsertElements.fluid.html @@ -0,0 +1,9 @@ + + + diff --git a/Resources/Private/Backend/Partials/FormEditor/Modals/InsertPages.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Modals/InsertPages.fluid.html new file mode 100644 index 0000000..7701748 --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Modals/InsertPages.fluid.html @@ -0,0 +1,9 @@ + + + diff --git a/Resources/Private/Backend/Partials/FormEditor/Modals/ValidationErrors.fluid.html b/Resources/Private/Backend/Partials/FormEditor/Modals/ValidationErrors.fluid.html new file mode 100644 index 0000000..df3901b --- /dev/null +++ b/Resources/Private/Backend/Partials/FormEditor/Modals/ValidationErrors.fluid.html @@ -0,0 +1,18 @@ + +
+
+
+
+

+
+
+
+
+ +
+
+
+
+
+
+ diff --git a/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html b/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html new file mode 100644 index 0000000..2bab789 --- /dev/null +++ b/Resources/Private/Backend/Templates/FormEditor/InlineTemplates.fluid.html @@ -0,0 +1,7 @@ + + + + + diff --git a/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml b/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml new file mode 100644 index 0000000..d1297b6 --- /dev/null +++ b/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/BlankForm.yaml @@ -0,0 +1,8 @@ +type: 'Form' +identifier: 'blankForm' +label: '[Blank Form]' +renderables: + - + type: 'Page' + identifier: 'page-1' + label: 'Step' \ No newline at end of file diff --git a/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml b/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml new file mode 100644 index 0000000..2614720 --- /dev/null +++ b/Resources/Private/Backend/Templates/FormEditor/Yaml/NewForms/SimpleContactForm.yaml @@ -0,0 +1,86 @@ +identifier: ext-form-simple-contact-form-example +label: 'Simple Contact Form' +type: Form + +finishers: + - + identifier: EmailToReceiver + options: + subject: 'Your message: {subject}' + recipients: + your.company@example.com: 'Your Company name' + senderAddress: '{email}' + senderName: '{name}' + replyToRecipients: {} + carbonCopyRecipients: {} + blindCarbonCopyRecipients: {} + format: 'html' + attachUploads: 'true' + translation: + language: '' + title: 'Confirmation of your message' + +renderables: + - + identifier: page-1 + label: 'Contact Form' + type: Page + + renderables: + - + defaultValue: '' + identifier: name + label: 'Name' + type: Text + properties: + fluidAdditionalAttributes: + placeholder: 'Name' + autocomplete: name + required: required + validators: + - + identifier: NotEmpty + - + defaultValue: '' + identifier: subject + label: 'Subject' + type: Text + properties: + fluidAdditionalAttributes: + placeholder: 'Subject' + required: required + validators: + - + identifier: NotEmpty + - + defaultValue: '' + identifier: email + label: 'Email' + type: Email + properties: + fluidAdditionalAttributes: + placeholder: 'Email address' + autocomplete: email + required: required + validators: + - + identifier: NotEmpty + - + identifier: EmailAddress + - + defaultValue: '' + identifier: message + label: 'Message' + type: Textarea + properties: + fluidAdditionalAttributes: + placeholder: '' + required: required + validators: + - + identifier: NotEmpty + + - + identifier: summarypage + label: 'Summary page' + type: SummaryPage diff --git a/Resources/Private/Frontend/Partials/AdvancedPassword.fluid.html b/Resources/Private/Frontend/Partials/AdvancedPassword.fluid.html new file mode 100644 index 0000000..51a20c8 --- /dev/null +++ b/Resources/Private/Frontend/Partials/AdvancedPassword.fluid.html @@ -0,0 +1,55 @@ + + + + + + + + + + +
+ + + + {formvh:translateElementProperty(element: element, property: 'passwordDescription')} + +
+
+ + + + +
+ + + + {formvh:translateElementError(element: element, error: error)} +
+
+
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/Checkbox.fluid.html b/Resources/Private/Frontend/Partials/Checkbox.fluid.html new file mode 100644 index 0000000..5f01cf8 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Checkbox.fluid.html @@ -0,0 +1,28 @@ + + + + + + + + + + {f:if(condition: '{validationResults.errors}', then: ' {element.rootForm.renderingOptions.fieldProperties.errorClassAttribute}')} + + +
+ + +
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/ContentElement.fluid.html b/Resources/Private/Frontend/Partials/ContentElement.fluid.html new file mode 100644 index 0000000..4f9efe4 --- /dev/null +++ b/Resources/Private/Frontend/Partials/ContentElement.fluid.html @@ -0,0 +1,27 @@ + + + + +
+ + + + + + + + +
+
+ + +
+ {element.properties.contentElementUid} +
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/CountrySelect.fluid.html b/Resources/Private/Frontend/Partials/CountrySelect.fluid.html new file mode 100644 index 0000000..f6bf9f4 --- /dev/null +++ b/Resources/Private/Frontend/Partials/CountrySelect.fluid.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Date.fluid.html b/Resources/Private/Frontend/Partials/Date.fluid.html new file mode 100644 index 0000000..97da612 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Date.fluid.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Email.fluid.html b/Resources/Private/Frontend/Partials/Email.fluid.html new file mode 100644 index 0000000..55aadb2 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Email.fluid.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Field/Field.fluid.html b/Resources/Private/Frontend/Partials/Field/Field.fluid.html new file mode 100644 index 0000000..dcf6d1c --- /dev/null +++ b/Resources/Private/Frontend/Partials/Field/Field.fluid.html @@ -0,0 +1,43 @@ + + + + +
+ {formvh:translateElementProperty(element: element, property: 'label')} + + + + + +
+
+ +
+ + + + +
+
+
+
+ + + {elementContent} + + + + {formvh:translateElementError(element: element, error: error)} +
+
+
+
+ + {formvh:translateElementProperty(element: element, property: 'elementDescription')} + +
+ diff --git a/Resources/Private/Frontend/Partials/Field/Required.fluid.html b/Resources/Private/Frontend/Partials/Field/Required.fluid.html new file mode 100644 index 0000000..50e5d30 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Field/Required.fluid.html @@ -0,0 +1,3 @@ + +* + diff --git a/Resources/Private/Frontend/Partials/Fieldset.fluid.html b/Resources/Private/Frontend/Partials/Fieldset.fluid.html new file mode 100644 index 0000000..087fcb9 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Fieldset.fluid.html @@ -0,0 +1,19 @@ + + + + + + + + + +
f:format.raw()}> + + {formvh:translateElementProperty(element: element, property: 'label')} + + + + +
+
+ diff --git a/Resources/Private/Frontend/Partials/FileUpload.fluid.html b/Resources/Private/Frontend/Partials/FileUpload.fluid.html new file mode 100644 index 0000000..13af954 --- /dev/null +++ b/Resources/Private/Frontend/Partials/FileUpload.fluid.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + +
    + +
  • + {file.originalResource.originalFile.name} + + + +
  • +
    +
+
+ +
+ {resource.originalResource.originalFile.name} + + + +
+
+
+
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/Form/Navigation.fluid.html b/Resources/Private/Frontend/Partials/Form/Navigation.fluid.html new file mode 100644 index 0000000..d8c04b4 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Form/Navigation.fluid.html @@ -0,0 +1,17 @@ + + + diff --git a/Resources/Private/Frontend/Partials/GridColumn.fluid.html b/Resources/Private/Frontend/Partials/GridColumn.fluid.html new file mode 100644 index 0000000..c6d5302 --- /dev/null +++ b/Resources/Private/Frontend/Partials/GridColumn.fluid.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Resources/Private/Frontend/Partials/GridRow.fluid.html b/Resources/Private/Frontend/Partials/GridRow.fluid.html new file mode 100644 index 0000000..a0813cc --- /dev/null +++ b/Resources/Private/Frontend/Partials/GridRow.fluid.html @@ -0,0 +1,13 @@ + + +
+ + +
+ +
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/Hidden.fluid.html b/Resources/Private/Frontend/Partials/Hidden.fluid.html new file mode 100644 index 0000000..c1af855 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Hidden.fluid.html @@ -0,0 +1,10 @@ + + + + + diff --git a/Resources/Private/Frontend/Partials/Honeypot.fluid.html b/Resources/Private/Frontend/Partials/Honeypot.fluid.html new file mode 100644 index 0000000..aae3f35 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Honeypot.fluid.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/ImageUpload.fluid.html b/Resources/Private/Frontend/Partials/ImageUpload.fluid.html new file mode 100644 index 0000000..c30aa12 --- /dev/null +++ b/Resources/Private/Frontend/Partials/ImageUpload.fluid.html @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+ + + + + + + diff --git a/Resources/Private/Frontend/Partials/MultiCheckbox.fluid.html b/Resources/Private/Frontend/Partials/MultiCheckbox.fluid.html new file mode 100644 index 0000000..bf3e5a8 --- /dev/null +++ b/Resources/Private/Frontend/Partials/MultiCheckbox.fluid.html @@ -0,0 +1,44 @@ + + + + + {f:if(condition: '{validationResults.errors}', then: '{element.rootForm.renderingOptions.fieldProperties.errorClassAttribute}')} + +
+ + + + + + + + +
+ +
+
+
+ + + + {formvh:translateElementError(element: element, error: error)} +
+
+
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/MultiSelect.fluid.html b/Resources/Private/Frontend/Partials/MultiSelect.fluid.html new file mode 100644 index 0000000..b70fe09 --- /dev/null +++ b/Resources/Private/Frontend/Partials/MultiSelect.fluid.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Number.fluid.html b/Resources/Private/Frontend/Partials/Number.fluid.html new file mode 100644 index 0000000..16631f5 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Number.fluid.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Page.fluid.html b/Resources/Private/Frontend/Partials/Page.fluid.html new file mode 100644 index 0000000..487abdf --- /dev/null +++ b/Resources/Private/Frontend/Partials/Page.fluid.html @@ -0,0 +1,10 @@ + + + +

{formvh:translateElementProperty(element: page, property: 'label')}

+
+ + + +
+ diff --git a/Resources/Private/Frontend/Partials/Password.fluid.html b/Resources/Private/Frontend/Partials/Password.fluid.html new file mode 100644 index 0000000..a0e8b50 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Password.fluid.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/RadioButton.fluid.html b/Resources/Private/Frontend/Partials/RadioButton.fluid.html new file mode 100644 index 0000000..13ea136 --- /dev/null +++ b/Resources/Private/Frontend/Partials/RadioButton.fluid.html @@ -0,0 +1,43 @@ + + + + + + {f:if(condition: '{validationResults.errors}', then: '{element.rootForm.renderingOptions.fieldProperties.errorClassAttribute}')} +
+ + + + + + + + +
+ +
+
+
+ + + + {formvh:translateElementError(element: element, error: error)} +
+
+
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/SingleSelect.fluid.html b/Resources/Private/Frontend/Partials/SingleSelect.fluid.html new file mode 100644 index 0000000..b01ee7a --- /dev/null +++ b/Resources/Private/Frontend/Partials/SingleSelect.fluid.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/StaticText.fluid.html b/Resources/Private/Frontend/Partials/StaticText.fluid.html new file mode 100644 index 0000000..5ee9aac --- /dev/null +++ b/Resources/Private/Frontend/Partials/StaticText.fluid.html @@ -0,0 +1,12 @@ + + +
+ +

{formvh:translateElementProperty(element: element, property: 'label')}

+
+ + {formvh:translateElementProperty(element: element, property: 'text') -> f:sanitize.html() -> f:transform.html()}
+ + +
+ diff --git a/Resources/Private/Frontend/Partials/SummaryPage.fluid.html b/Resources/Private/Frontend/Partials/SummaryPage.fluid.html new file mode 100644 index 0000000..ca04e9b --- /dev/null +++ b/Resources/Private/Frontend/Partials/SummaryPage.fluid.html @@ -0,0 +1,79 @@ + + +
+ + {formvh:translateElementProperty(element: page, property: 'label')} + +
+ + + + +

{formvh:translateElementProperty(element: formValue.element, property: 'label')}

+
+ +
+
{formvh:translateElementProperty(element: formValue.element, property: 'label') -> f:sanitize.html() -> f:transform.html()}
+
+ + + + + + +
    + +
  • + +
  • +
    +
+
+ + + +
+
+ + + +
    + +
  • {value.originalResource.originalFile.name}
  • +
    +
+
+ + {formValue.processedValue} + +
+
+ + + +
    + +
  • {value}
  • +
    +
+
+ + {formValue.processedValue} + +
+
+
+
+ + - + +
+
+
+
+
+
+
+
+
+ diff --git a/Resources/Private/Frontend/Partials/Telephone.fluid.html b/Resources/Private/Frontend/Partials/Telephone.fluid.html new file mode 100644 index 0000000..8fa830c --- /dev/null +++ b/Resources/Private/Frontend/Partials/Telephone.fluid.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Text.fluid.html b/Resources/Private/Frontend/Partials/Text.fluid.html new file mode 100644 index 0000000..8f6e435 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Text.fluid.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/Textarea.fluid.html b/Resources/Private/Frontend/Partials/Textarea.fluid.html new file mode 100644 index 0000000..abb00bd --- /dev/null +++ b/Resources/Private/Frontend/Partials/Textarea.fluid.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Partials/UnknownElement.fluid.html b/Resources/Private/Frontend/Partials/UnknownElement.fluid.html new file mode 100644 index 0000000..ffa1faf --- /dev/null +++ b/Resources/Private/Frontend/Partials/UnknownElement.fluid.html @@ -0,0 +1,3 @@ + + + diff --git a/Resources/Private/Frontend/Partials/Url.fluid.html b/Resources/Private/Frontend/Partials/Url.fluid.html new file mode 100644 index 0000000..a319d26 --- /dev/null +++ b/Resources/Private/Frontend/Partials/Url.fluid.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/Resources/Private/Frontend/Templates/Finishers/Confirmation/Confirmation.fluid.html b/Resources/Private/Frontend/Templates/Finishers/Confirmation/Confirmation.fluid.html new file mode 100644 index 0000000..374ea00 --- /dev/null +++ b/Resources/Private/Frontend/Templates/Finishers/Confirmation/Confirmation.fluid.html @@ -0,0 +1,5 @@ + +
+ {message -> f:sanitize.html() -> f:transform.html()} +
+ diff --git a/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.html b/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.html new file mode 100644 index 0000000..ecf1d5f --- /dev/null +++ b/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.html @@ -0,0 +1,53 @@ + + +{title} + + {messageBefore -> f:sanitize.html() -> f:format.html()} + + + + + + + + + + + + + + + +
{formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey)}{formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey) -> f:sanitize.html() -> f:transform.html()} + + + + + + + + + + +
{value}
+
+ + + + + +
{formValue.processedValue}
+
+
+
+ + - + +
+
+
+ {messageAfter -> f:sanitize.html() -> f:format.html()} +
+ diff --git a/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.txt b/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.txt new file mode 100644 index 0000000..17ab3c9 --- /dev/null +++ b/Resources/Private/Frontend/Templates/Finishers/Email/Default.fluid.txt @@ -0,0 +1,19 @@ + +{title} + +{messageBefore -> f:format.stripTags()} + + + + + *** {formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey)} ***{formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey) -> f:format.stripTags()}: - {singleValue} + + + + *** {formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey)} ***{formvh:translateElementProperty(element: formValue.element, property: 'label', languageKey: languageKey) -> f:format.stripTags()}: {formValue.processedValue -> f:format.raw()}- + + + + +{messageAfter -> f:format.stripTags()} + diff --git a/Resources/Private/Frontend/Templates/Finishers/Error.fluid.html b/Resources/Private/Frontend/Templates/Finishers/Error.fluid.html new file mode 100644 index 0000000..892f9e4 --- /dev/null +++ b/Resources/Private/Frontend/Templates/Finishers/Error.fluid.html @@ -0,0 +1,3 @@ + +

{message}

+ diff --git a/Resources/Private/Frontend/Templates/Form.fluid.html b/Resources/Private/Frontend/Templates/Form.fluid.html new file mode 100644 index 0000000..c9f570e --- /dev/null +++ b/Resources/Private/Frontend/Templates/Form.fluid.html @@ -0,0 +1,21 @@ + + + + +
+ +
+
+
+ diff --git a/Resources/Private/Frontend/Templates/Render.fluid.html b/Resources/Private/Frontend/Templates/Render.fluid.html new file mode 100644 index 0000000..674d3fa --- /dev/null +++ b/Resources/Private/Frontend/Templates/Render.fluid.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/Resources/Private/Language/Database.xlf b/Resources/Private/Language/Database.xlf new file mode 100644 index 0000000..7a30149 --- /dev/null +++ b/Resources/Private/Language/Database.xlf @@ -0,0 +1,1337 @@ + + + +
+ + + Form manager + + + Default + + + [Empty] + + + Form definition + + + General + + + Please select a form definition + + + Override finisher settings + + + There are no finishers or finisher options in the current form definition. + + + No form selected. + + + Invalid form "%s". + + + "%s" (no read access). + + + The form "%s" does not exist. + + + "%s" (Invalid ext:form configuration). + + + Invalid ext:form configuration in form "%s": %s + + + Invalid configuration. + + + Confirmation + + + Text + + + Record + + + Email to sender (form submitter) + + + Subject of the email + + + Recipients + + + Recipient + + + Email Address + + + Name + + + Email address of the sender + + + Human-readable name of the sender + + + Reply-To Recipients + + + Reply-To Recipient + + + CC Recipients + + + CC Recipient + + + BCC Recipients + + + BCC Recipient + + + Add HTML mail part + + + Translation language + + + Auto + + + EN + + + Message + + + Title + + + Email to receiver (you) + + + Subject of the email + + + Email addresses and human-readable names of the recipients + + + Email address of the sender + + + Human-readable name of the sender + + + Reply-To Recipients + + + CC Recipients + + + BCC Recipients + + + Add HTML part + + + Translation language + + + Auto + + + EN + + + Message + + + Title + + + Redirect + + + Page + + + Additional link parameter + + + Add fragment to the redirect link + + + Delete error + + + The form "%s" could not be deleted. + + + Form Management + + + Create new form + + + Form name + + + Integrity + + + Location + + + References + + + Options + + + Edit this form + + + Duplicate this form + + + Delete this form + + + No forms exist + + + Once created, forms will be displayed here. + + + There are currently no forms found containing the search term "%1s". + + + Remove search term + + + Invalid form definition + + + Read only + + + Duplicate identifier + + + form + + + forms + + + Standard + + + Blank form + + + Simple contact form (ext:form example) + + + Show History + + + Form editor + + + Loading... + + + Loading... + + + Save + + + Edit form properties + + + Undo + + + Redo + + + Toggle structure + + + Toggle inspector + + + Show inspector + + + Hide inspector + + + Create new step + + + Previous step + + + Next step + + + Step name is not set + + + Preview mode + + + Edit mode + + + Structure + + + Insert elements + + + Required + + + Not a number + + + Invalid email address + + + Invalid form element + + + Invalid file size format, valid e.g. "10B|K|M|G" + + + Invalid date format. Use Y-m-d (e.g. 2018-03-17) or a relative expression (e.g. today, -18 years) + + + Invalid pattern + + + Not all items are numbers + + + Invalid number of items. Minimum is {0}, maximum is {1} + + + Basic elements + + + Special elements + + + Select elements + + + Advanced elements + + + Container elements + + + Step types + + + Form name + + + Save + + + The form has been successfully saved. + + + Save + + + The form could not be saved: + + + Alert + + + Some elements are not configured properly. Please check the following elements: + + + OK + + + New element + + + New step + + + Remove element? + + + Remove this element? + + + Remove + + + Cancel + + + Error + + + There must be at least one step within your form. + + + You currently have unsaved changes. Closing the form will discard them. Continue? + + + Quit without saving? + + + Discard changes + + + Keep editing + + + Step {0} of {1} + + + Minimum + + + Maximum + + + Placeholder + + + Default value + + + Pattern + + + Additional client-side validation as JavaScript regular expression + + + Step + + + Validators + + + Add validator + + + Alphanumeric + + + Non-XML text + + + String length + + + Email + + + Integer number + + + Floating-point number + + + Number + + + Number range + + + Regular expression + + + Number of submitted values + + + Alphanumeric + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Non-XML text + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + String length + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Email + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Integer number + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Floating-point number + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Number + + + Number range + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Regular expression + + + Regular expression + + + Enter a valid PHP PCRE regular expression here. + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Number of submitted values + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + First option (empty value) + + + If set, this label will be shown as first option. + + + Choices + + + Validators + + + Add validator + + + Uploads save path + + + Validators + + + Add validator + + + File size + + + Number of files + + + File size + + + Number of uploaded files + + + Submit label + + + Submit + + + Finishers + + + Add finisher + + + Email to sender (form submitter) + + + Email to receiver (you) + + + Redirect to a page + + + Delete uploads + + + Confirmation message + + + Email to sender (form submitter) + + + Subject + + + Message + + + Optional custom message. Use {formValues} as a placeholder to include the submitted form data at that position. If empty, only the form data table will be shown. + + + Recipients + + + The email addresses and names of the website visitors to which the email should be sent. + + + Email Address + + + Name + + + Sender address + + + The email address of the sender (e.g. your company's email address) which appears in the website visitor email client. + + + Sender name + + + The name of the sender (e.g. your company's name) which appears in the website visitor email client. + + + Reply-To Recipients + + + CC Recipients + + + BCC Recipients + + + Add HTML part + + + If enabled, the email will contain a plaintext and an HTML part, otherwise only a plaintext part. + + + Attach uploads + + + Translation language + + + Auto + + + EN + + + Title + + + The title, being shown in the Email. The title is rendered in the header section right above the email body. Do not confuse this field with the subject of your email. + + + Email to receiver (you) + + + Subject + + + Message + + + Optional custom message. Use {formValues} once as a placeholder to include the submitted form data at that position (only the first occurrence is replaced). If empty, only the form data table will be shown. + + + Recipients + + + The email addresses and names of the recipients to which the email should be sent (e.g. your company's email addresses). + + + Sender address + + + The email address of the sender which appears in your email client. Use the "insert formelement identifier" dropdown if you need to select a form element which contains the website visitor's email address instead. + + + Sender name + + + The name of the sender which appears in your email client. Use the "insert formelement identifier" dropdown if you need to choose one or more form elements which contain the website visitor's name + + + Reply-To Recipients + + + CC Recipients + + + BCC Recipients + + + Add HTML part + + + If enabled, the email will contain a plaintext and an HTML part, otherwise only a plaintext part. + + + Attach uploads + + + Translation language + + + Auto + + + EN + + + Title + + + The title, being shown in the Email. The title is rendered in the header section right above the email body. Do not confuse this field with the subject of your email. + + + Redirect to a page + + + Page + + + Page + + + Additional parameters + + + URL fragment + + + Page Content + + + You can use a content element identifier as URL fragment or set a custom fragment identifier. + + + Delete uploads + + + Confirmation message + + + Content element uid + + + Page Content + + + Text + + + Will be ignored if "Content element" is set + + + Execute a closure + + + Flash message + + + Save the mail to the Database + + + Label + + + Label + + + Description + + + Field visible + + + Autocomplete + + + None + + + off - disable the autocomplete functionality + + + name - Full name + + + Prefix or title (e.g., "Mr.", "Ms.", "Dr.") + + + given-name - first name + + + additional-name - middle name + + + family-name - last name + + + honorific-suffix - Name suffix (e.g., "Jr.", "II") + + + Nickname, screen name + + + organization-title - Job title + + + username + + + organization - Company name + + + address-line1 - Street address, line 1 + + + address-line2 - Street address, line 2 + + + address-level1 - State, Canton etc + + + address-level2 - City + + + country-name + + + postal-code - ZIP + + + tel - Full telephone number + + + impp - URL representing an instant messaging protocol endpoint + + + sex - Gender identity + + + language - Preferred language + + + street-address + + + tel-country-code - Country code component of the telephone number + + + tel-national - Telephone number without the county code + + + tel-area-code - Area code component of the telephone number + + + tel-local - Telephone number without the country code and area code component + + + tel-extension - Telephone number internal extension code + + + url - Home page + + + new-password - A new password to create / change + + + current-password - Current password for the selected username + + + bday-day - Day component of birthday + + + bday-month - Month component of birthday + + + bday-year - Year component of birthday + + + photo + + + email + + + bday - Birthday + + + country - Country code + + + Field required + + + Custom error message + + + Error message which is shown if the validation does not succeed + + + Date range + + + Grid viewport configuration + + + Extra small + + + Small + + + Medium + + + Large + + + Extra large + + + Extra extra large + + + Numbers of columns for viewport "{@viewPortLabel}" + + + Leave empty for auto calculation + + + Step + + + A form step that can be customized with various elements + + + Step name + + + Previous button label + + + Previous step + + + Next button label + + + Next step + + + Summary step + + + A form step that displays all entered values for review before submission + + + Step name + + + Previous button label + + + Previous step + + + Next button label + + + Next step + + + Fieldset + + + A container used to group related form elements, improving accessibility and providing content-based structure + + + Fieldset name + + + Grid: Column + + + A container element for arranging fields, providing visual structure + + + Name (not visible within frontend) + + + Grid: Row + + + A container element for arranging fields side by side, providing visual structuring + + + Row name (not visible within frontend) + + + Text + + + A single-line text field + + + Email address + + + A text field for inputting an email address + + + Telephone number + + + A text field for inputting a phone number + + + URL + + + A text field for inputting a URL + + + Number + + + A text field for inputting numbers, with browser controls to adjust the value in predefined steps + + + Number + + + Date + + + A text field for inputting a date in a single line + + + A date in format Y-m-d (e.g 2018-03-17) + + + Specify the number of days between each occurrence of this event. + + + Frequency + + + Date range + + + Date range + + + Minimum date + + + Maximum date + + + Password + + + A text field for entering a password + + + Advanced password + + + A text field for entering and confirming a password + + + Confirmation label + + + Confirmation + + + Textarea + + + A multi-line text field for entering extended or continuous text + + + Checkbox + + + An element for creating a single checkbox + + + Country select + + + An element to select a country + + + Multi checkbox + + + An element for creating multiple checkboxes + + + Multi select + + + An element for creating a field that allows multiple selections + + + Radio button + + + An element for displaying one or more radio buttons + + + Single select + + + An element for creating a dropdown list for selecting a single option + + + Date/time + + + Static text + + + A field for displaying text content + + + Header + + + Text + + + Hidden + + + A field that is not displayed in the frontend + + + Value + + + Content element + + + A field for displaying any content element from your website + + + No content element selected + + + Content element uid + + + Page Content + + + File upload + + + An element for uploading a file + + + Allowed file mime types + + + +Your servers' maximum upload file size is {0}. Be aware setting higher values can result in errors when submitting the form. +If you need higher values contact your administrator for help. + + + + Documents (doc) + + + Documents (docx) + + + Documents (xls) + + + Documents (xlsx) + + + Documents (pdf) + + + Documents (odt) + + + Documents (ods) + + + Allow multiple upload + + + Allow removal of uploaded files + + + Image upload + + + An element for uploading an image + + + Allowed file mime types + + + Images (jpg) + + + Images (png) + + + Images (bmp) + + + Country Select + + + Prioritized countries + + + Only countries + + + Exclude countries + + + Default value + + + Ensure the selected country is not excluded by the configured country filters. + + + Unknown element + + + Create new element + + + Remove + + + Insert formelement identifier + + + Remove this Element + + + Add a new row + + + Remove this row + + + Move this row + + + Label + + + Value + + + Selected + + + Unfortunately no element type matches your query, please try a different one. + + + Search for any element type + + + Unfortunately no step type matches your query, please try a different one. + + + Search for any step type + + + Database + + + Store the form as a record in the database. Recommended for most use cases, because it treats forms as user-generated content and allows integrated versioning. + + + Extension + + + Store the form inside an extension. Such forms are then not meant for editing, but provided as-is. + + + + diff --git a/Resources/Private/Language/Modules/form_editor.xlf b/Resources/Private/Language/Modules/form_editor.xlf new file mode 100644 index 0000000..ba7e023 --- /dev/null +++ b/Resources/Private/Language/Modules/form_editor.xlf @@ -0,0 +1,17 @@ + + + +
+ + + Form Editor + + + Build and customize forms using the visual form editor. Add fields, configure validations, and set up finishers. + + + Edit forms + + + + diff --git a/Resources/Private/Language/Modules/form_manager.xlf b/Resources/Private/Language/Modules/form_manager.xlf new file mode 100644 index 0000000..a1bd5a4 --- /dev/null +++ b/Resources/Private/Language/Modules/form_manager.xlf @@ -0,0 +1,17 @@ + + + +
+ + + Form Manager + + + Manage and organize all forms. Create, edit, duplicate, and delete forms. + + + Manage forms + + + + diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf new file mode 100644 index 0000000..fde8d4d --- /dev/null +++ b/Resources/Private/Language/locallang.xlf @@ -0,0 +1,155 @@ + + + +
+ + + Uploaded image + + + This field is mandatory. + + + This field is mandatory. + + + This field is mandatory. + + + This field is mandatory. + + + You must enter a valid date. + + + You can only enter letters or digits. + + + You can only enter non formatted text without any markup (e.g without XML tags). + + + You can only enter non formatted text without any markup (e.g without XML tags). + + + You can only enter non formatted text without any markup (e.g without XML tags). + + + Your text must be a minimum of %s characters in length and no longer than %s. + + + You must enter text which is longer than %s characters. + + + You must enter text which is no longer than %s characters. + + + You must enter a valid email address. + + + You must enter a valid number. + + + You must enter a valid floating point number. + + + You must enter a valid number. + + + You must enter a valid number between %s and %s. + + + You must enter a valid value. Please refer to the description of this field. + + + You must enter a countable subject. + + + You must select between %s to %s elements. + + + You must enter an instance of \TYPO3\CMS\Extbase\Domain\Model\FileReference or \TYPO3\CMS\Core\Resource\File. + + + You entered an incorrect media type, "%s" is not allowed for this file. Please refer to the description of this field. + + + The file extension provided "%s" does not match to expected media types. Please refer to the description of this field. + + + You must NOT fill this field. + + + You must enter an instance of \TYPO3\CMS\Extbase\Domain\Model\FileReference or \TYPO3\CMS\Core\Resource\File. + + + You must select a file that is larger than %s in size. + + + You must select a file that is no larger than %s. + + + You must enter an instance of \DateTime. + + + You must select a date before %s. + + + You must select a date after %s. + + + This field cannot be validated due to a configuration error. Please contact the website owner. + + + Password does not match confirmation + + + Form + + + A form that allows website users to submit messages. + + + Maximum file size exceeded. + + + Upload failed. The file was only partially uploaded, please try again. + + + No file was uploaded. + + + Upload failed. + + + Remove + + + Form: YAML Configuration + + + Your form could not be submitted due to a technical issue. It might be a temporary issue, but can also be related to your input. + + + Previous + + + Next + + + First + + + Last + + + Forms + + + Page + + + Refresh + + + + diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf new file mode 100644 index 0000000..03a5ebd --- /dev/null +++ b/Resources/Private/Language/locallang_db.xlf @@ -0,0 +1,20 @@ + + + +
+ + + Form definition + + + Name + + + Identifier + + + Configuration + + + + diff --git a/Resources/Private/Language/locallang_formEditor_failSafeErrorHandling_javascript.xlf b/Resources/Private/Language/locallang_formEditor_failSafeErrorHandling_javascript.xlf new file mode 100644 index 0000000..1ad5bf5 --- /dev/null +++ b/Resources/Private/Language/locallang_formEditor_failSafeErrorHandling_javascript.xlf @@ -0,0 +1,17 @@ + + + +
+ + + The form editor has stopped working. + + + Please contact your administrator. + + + Technical Reason: + + + + diff --git a/Resources/Private/Language/locallang_formManager_javascript.xlf b/Resources/Private/Language/locallang_formManager_javascript.xlf new file mode 100644 index 0000000..bfcaa63 --- /dev/null +++ b/Resources/Private/Language/locallang_formManager_javascript.xlf @@ -0,0 +1,161 @@ + + + +
+ + + Name + + + Enter a meaningful and descriptive name for the form. The name is displayed only in the TYPO3 backend. + + + New form name + + + Location + + + Select the location where the form will be saved. + + + Form prototype + + + Template + + + Select a template for building your new form. + + + General + + + Copied form + + + Cancel + + + Delete + + + Confirm deletion + + + Delete form "{0}"? Forms saved as files are permanently deleted and cannot be restored from the Recycler. + + + Create new form + + + Mode + + + Choose + + + You do not have permission to create forms. Please contact your administrator. + + + Settings + + + Ready? + + + Check + + + Just check and confirm the settings you have entered. Done? Then you are ready to go. + + + Check and confirm + + + Create + + + The form could not be saved + + + Storage location + + + Choose how the form should be saved: + + + Storage + + + Storage + + + Duplicate form "{0}" + + + Ready? + + + Check + + + Check and confirm + + + Just check and confirm the settings you have entered. Done? Then you are ready to go. + + + Duplicate + + + The form could not be saved + + + There are no references yet. + + + Control + + + Uid + + + Title + + + Edit + + + Form: {0} + + + References to this item + + + Blank form + + + Start fresh + + + Create a new form from scratch. + + + Predefined form + + + Use a form template + + + Create a new form and use an existing form template for it. + + + Form created + + + The form has been successfully created. Click "Finish" to be redirected to the newly created form. + + + + diff --git a/Resources/Private/Language/locallang_form_editor_javascript.xlf b/Resources/Private/Language/locallang_form_editor_javascript.xlf new file mode 100644 index 0000000..fbdd8be --- /dev/null +++ b/Resources/Private/Language/locallang_form_editor_javascript.xlf @@ -0,0 +1,32 @@ + + + +
+ + + Insert elements + + + Create new element + + + Create new element after + + + Create new element before + + + Remove + + + Step name is not set + + + Has validation errors + + + Contains elements with validation errors + + + + diff --git a/Resources/Private/Language/locallang_relative_date_editor.xlf b/Resources/Private/Language/locallang_relative_date_editor.xlf new file mode 100644 index 0000000..96db9e5 --- /dev/null +++ b/Resources/Private/Language/locallang_relative_date_editor.xlf @@ -0,0 +1,44 @@ + + + +
+ + + No value + + + Today + + + Absolute date + + + Relative date + + + past + + + future + + + {count, plural, one {Day} other {Days}} + + + {count, plural, one {Week} other {Weeks}} + + + {count, plural, one {Month} other {Months}} + + + {count, plural, one {Year} other {Years}} + + + Custom relative expression + + + e.g. "sunday next month" + + + + diff --git a/Resources/Private/Language/module.xlf b/Resources/Private/Language/module.xlf new file mode 100644 index 0000000..e595b3c --- /dev/null +++ b/Resources/Private/Language/module.xlf @@ -0,0 +1,17 @@ + + + +
+ + + Build custom forms + + + This module ships a flexible and user-friendly form editor. It allows you to build and create versatile forms for your frontend. Your forms can easily be added to any page by using the content element "Form". Within this element, finishers can be overridden. + + + Forms + + + + diff --git a/Resources/Private/Partials/Backend/FormManager/Pagination.fluid.html b/Resources/Private/Partials/Backend/FormManager/Pagination.fluid.html new file mode 100644 index 0000000..caa3d0f --- /dev/null +++ b/Resources/Private/Partials/Backend/FormManager/Pagination.fluid.html @@ -0,0 +1,90 @@ + + + diff --git a/Resources/Private/Templates/Backend/FormEditor/Index.fluid.html b/Resources/Private/Templates/Backend/FormEditor/Index.fluid.html new file mode 100644 index 0000000..5003bb0 --- /dev/null +++ b/Resources/Private/Templates/Backend/FormEditor/Index.fluid.html @@ -0,0 +1,110 @@ + + + + + +
+
+ +
+
+
+ + +
+
+
+ + +
+

+
+ + +
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+ +
+ + +
+ +
+
+
+
+
+
+
+
+
+ + +
+
+ + diff --git a/Resources/Private/Templates/Backend/FormManager/Index.fluid.html b/Resources/Private/Templates/Backend/FormManager/Index.fluid.html new file mode 100644 index 0000000..df8253f --- /dev/null +++ b/Resources/Private/Templates/Backend/FormManager/Index.fluid.html @@ -0,0 +1,333 @@ + + + + + + + + + + + +

+ +
+
+
+ +
+ + +
+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + {f:translate(key: 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels._CONTROL_')} +
+ + + + + {form.name} + + + + + + + + + + + {form.name} + + + + {form.name} + + + + + + {form.storageLocation} + + + + + + + + + + + + + + + + + + {form.referenceCount} + + + - + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + {totalAmountOfPaginatedItems} + {totalAmountOfPaginatedItems} + +
+
+ +
+ + +

+ + + +
+
+ + +

+ +
+
+
+
+ + + + + + diff --git a/Resources/Public/Css/form.css b/Resources/Public/Css/form.css new file mode 100644 index 0000000..ba20dff --- /dev/null +++ b/Resources/Public/Css/form.css @@ -0,0 +1,108 @@ +/*! + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +.formeditor{--formeditor-module-gap:var(--module-body-padding-x);--formeditor-module-inspector:400px;--formeditor-inspector-color:var(--typo3-text-color-base);--formeditor-inspector-bg:var(--typo3-surface-container-low);--formeditor-inspector-border-width:var(--typo3-component-border-width);--formeditor-inspector-border-color:color-mix(in srgb,var(--formeditor-inspector-bg),var(--formeditor-inspector-color) var(--typo3-border-mix));--formeditor-inspector-border-radius:var(--typo3-component-border-radius);--formeditor-inspector-box-shadow:var(--typo3-component-box-shadow);--formeditor-stage-element-padding-y:.5rem;--formeditor-stage-element-padding-x:.75rem;--formeditor-stage-element-validator-width:100px;--formeditor-stage-spacing:1rem;--formeditor-stage-element-border-width:var(--typo3-component-border-width);--formeditor-stage-element-border-radius:var(--typo3-component-border-radius);--formeditor-stage-element-border-color-state:initial;--formeditor-stage-element-bg:var(--typo3-surface-bright);--formeditor-stage-element-color:var(--typo3-component-color);--formeditor-stage-element-border-color:var(--typo3-component-border-color);--formeditor-stage-element-hover-border-color:var(--typo3-component-hover-border-color);--formeditor-stage-element-active-border-color:var(--typo3-component-active-border-color);--formeditor-stage-element-hidden-bg:var(--typo3-surface-bright);--formeditor-stage-element-hidden-color:var(--typo3-component-color);--formeditor-stage-element-hidden-border-color:var(--typo3-component-border-color);position:relative} +[data-module-name=form_editor]{overflow-x:clip} +@media (max-width:949px){ +body:has(.formeditor-inspector-expanded){max-height:100dvh;overflow:hidden}} +.formeditor-loader{align-items:center;display:flex;flex-direction:column;gap:.25rem;inset:0;justify-content:center;overflow:hidden;position:absolute} +.formeditor-module,.formeditor-stage-container{flex-grow:1;min-height:0;min-width:0} +.formeditor-stage-container{position:relative} +.formeditor-stage-container-inner{position:relative;width:100%} +.formeditor-stage-container-inner>:last-child{margin-bottom:0} +.formeditor-header{align-items:center;display:flex;gap:1rem;justify-content:space-between;margin-bottom:var(--typo3-spacing)} +.formeditor-header h1{margin:0} +.formeditor-header-actions{align-items:center;display:flex;gap:.5rem} +.formeditor-inspector{border:var(--formeditor-inspector-border-width) solid var(--formeditor-inspector-border-color);color:var(--formeditor-inspector-color);display:flex;flex-direction:column;height:calc(100dvh - var(--module-docheader-height) - var(--module-body-padding-y));inset-inline-end:calc(var(--module-body-padding-x)*-1);position:absolute;top:calc((var(--module-body-padding-y) + var(--formeditor-inspector-border-width))*-1);width:calc(100% + var(--module-body-padding-x));z-index:var(--typo3-zindex-header);-webkit-border-end:0;background:var(--formeditor-inspector-bg);border-inline-end:0;border-radius:var(--formeditor-inspector-border-radius) 0 0 var(--formeditor-inspector-border-radius);box-shadow:var(--typo3-component-box-shadow-flyout);isolation:isolate;overflow:hidden;transform:translateX(100%);transition:transform .3s ease-out} +.formeditor-inspector.formeditor-inspector-expanded{transform:translateX(0)} +.formeditor-inspector-inner{flex-grow:1;min-height:0;overflow:auto;padding:var(--module-body-padding)} +.formeditor-inspector-collapse{display:flex;justify-content:flex-end;margin-bottom:calc(var(--typo3-spacing)/2)} +.formeditor-inspector-expand{display:inline-flex} +.formeditor-inspector-content .input-group{flex-wrap:nowrap} +.formeditor-inspector-content .input-group>:first-child{flex-grow:1} +.formeditor-inspector-content .input-group>:first-child>*{border-end-end-radius:0;border-start-end-radius:0} +.formeditor-inspector-content .input-group .input-group-btn .btn-group .btn{border-end-start-radius:0;border-start-start-radius:0} +.formeditor-inspector-content>.formeditor-inspector-element-remove-button{border-top:1px solid var(--module-docheader-border-color);padding-top:1rem} +.formeditor-inspector-content>.formeditor-inspector-element-remove-button .btn{width:100%} +.formeditor-inspector-element:last-child>:last-child{margin-bottom:0} +.formeditor-inspector-element-headline{border-bottom:1px solid color-mix(in srgb,transparent,currentColor 15%);margin-bottom:1.5rem;padding-bottom:1rem} +.formeditor-inspector-element-headline h2{align-items:center;display:flex;font-family:inherit;font-size:var(--typo3-font-size);font-weight:700;gap:.25rem;margin:0} +typo3-form-form-element-stage-item-toolbar{display:block} +.formeditor-stage{border:1px dotted color-mix(in srgb,var(--module-bg),currentColor 30%);border-radius:var(--formeditor-stage-element-border-radius);margin-bottom:var(--typo3-spacing);overflow-x:auto;overflow-y:hidden;padding:var(--module-body-padding)} +.formeditor-stage typo3-form-form-element-stage-item,.formeditor-stage typo3-form-page-stage-item{display:block} +.formeditor-stage .formeditor-page-title{cursor:pointer;font-size:.875rem;font-weight:700;margin:0 0 var(--typo3-spacing)} +.formeditor-stage .formeditor-page-title:empty:before{content:attr(data-empty-message);opacity:.75} +.formeditor-stage .formeditor-page-title:hover{text-decoration:underline;-webkit-text-decoration-color:color-mix(in srgb,currentColor,transparent 50%);text-decoration-color:color-mix(in srgb,currentColor,transparent 50%);text-underline-offset:.1em} +.formeditor-stage-section{background-color:var(--typo3-surface-container-base);border-radius:calc(var(--formeditor-stage-element-border-radius) - 3px)} +.formeditor-stage-heading{margin-bottom:var(--formeditor-stage-spacing)} +.formeditor-stage-area{padding:var(--formeditor-stage-spacing)} +.formeditor-list,.formeditor-stage-list{display:grid;gap:var(--formeditor-stage-spacing);grid-template-columns:minmax(0,1fr);list-style:none;margin:0;padding:0} +.formeditor-element{background-color:var(--formeditor-stage-element-bg);border:var(--formeditor-stage-element-border-width) solid var(--formeditor-stage-element-border-color-state,var(--formeditor-stage-element-border-color));border-radius:var(--formeditor-stage-element-border-radius);color:var(--formeditor-stage-element-color);display:flex;flex-direction:column;overflow:hidden} +.formeditor-element.formeditor-element-hidden:not(.formeditor-element.selected){background-color:var(--formeditor-stage-element-hidden-bg);border:var(--formeditor-stage-element-border-width) dashed var(--formeditor-stage-element-hidden-border-color);opacity:.5;transition:opacity .3s ease-in-out} +.formeditor-element.formeditor-element-hidden:not(.formeditor-element.selected):focus-within,.formeditor-element.formeditor-element-hidden:not(.formeditor-element.selected):hover{opacity:1} +.formeditor-element typo3-form-form-element-stage-item,.formeditor-element typo3-form-form-element-stage-item-toolbar{display:block} +.formeditor-element .formeditor-element-toolbar{align-items:center;display:flex;gap:.5rem;padding:var(--formeditor-stage-spacing)} +.formeditor-element .formeditor-element-toolbar-left,.formeditor-element .formeditor-element-toolbar-right{flex-shrink:0} +.formeditor-element .formeditor-element-toolbar-title{flex:1 1 0;font-weight:700;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.formeditor-element .formeditor-element-toolbar-label{font-weight:700} +.formeditor-element .formeditor-element-body{background-color:var(--formeditor-stage-element-bg);border-radius:calc(var(--formeditor-stage-element-border-radius) - var(--formeditor-stage-element-border-width));border-start-end-radius:0;border-start-start-radius:0;color:var(--formeditor-stage-element-color);display:flex;overflow:hidden;position:relative} +.formeditor-element .formeditor-element-info{display:flex;gap:var(--formeditor-stage-spacing);height:100%;padding:var(--formeditor-stage-spacing);position:relative;width:100%} +.formeditor-element .formeditor-element-info>*{flex:0 0 50%} +.formeditor-element .formeditor-element-info-label{align-items:flex-start;display:flex;font-weight:700;position:relative} +.formeditor-element .formeditor-element-info-content{align-items:center;display:flex;flex-flow:row wrap} +.formeditor-element .formeditor-element-validator{background-color:var(--typo3-component-hover-bg);border-start-start-radius:var(--formeditor-stage-element-border-radius);color:var(--typo3-component-hover-color);display:flex;height:100%;inset-inline-end:0;overflow:hidden;position:absolute;top:0;-webkit-margin-end:calc(var(--formeditor-stage-element-validator-width)*-1);margin-inline-end:calc(var(--formeditor-stage-element-validator-width)*-1);transition:margin .15s ease-in-out;z-index:2} +.formeditor-element .formeditor-element-validator:has(.formeditor-element-validator-icon:empty){display:none} +.formeditor-element .formeditor-element-validator-icon{height:100%} +.formeditor-element .formeditor-element-validator-icon .icon,.formeditor-element .formeditor-element-validator-icon typo3-backend-icon{height:100%;margin-inline:var(--formeditor-stage-element-padding-x);z-index:1} +.formeditor-element .formeditor-element-validator-list{align-items:center;display:flex;flex-flow:row wrap;gap:1px;height:100%;padding:var(--formeditor-stage-element-padding-y) var(--formeditor-stage-element-padding-x);-webkit-padding-start:0;font-size:var(--typo3-font-size-small);padding-inline-start:0;transition:margin .15s ease-in-out;width:var(--formeditor-stage-element-validator-width)} +.formeditor-element .formeditor-element-validator-list:hover{-webkit-margin-end:0;margin-inline-end:0} +.formeditor-element .formeditor-element-validator-list-item{opacity:.75;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%} +.formeditor-element:hover{--formeditor-stage-element-border-color-state:var(--formeditor-stage-element-hover-border-color)} +.formeditor-element:focus-visible{outline:var(--typo3-outline-width) var(--typo3-outline-style) color-mix(in srgb,var(--typo3-state-default-focus-border-color),transparent 25%);outline-offset:0} +.formeditor-element.selected{--formeditor-stage-element-border-color-state:var(--formeditor-stage-element-active-border-color);outline:2px solid var(--formeditor-stage-element-active-border-color);outline-offset:-1px} +.formeditor-element:has(+.formeditor-list){border-end-end-radius:0;border-end-start-radius:0} +.formeditor-element:has(+.formeditor-list) .formeditor-element-body{border-end-end-radius:0;border-end-start-radius:0} +.formeditor-element+.formeditor-list:not(:empty){border:var(--formeditor-stage-element-border-width) solid var(--formeditor-stage-element-border-color-state,var(--formeditor-stage-element-border-color));border-end-end-radius:var(--formeditor-stage-element-border-radius);border-end-start-radius:var(--formeditor-stage-element-border-radius);border-top:none;padding:var(--formeditor-stage-spacing)} +.formeditor-element.formeditor-element-hidden+.formeditor-list:not(:empty){background-color:var(--formeditor-stage-element-hidden-bg);border:var(--formeditor-stage-element-border-width) dashed var(--formeditor-stage-element-hidden-border-color);border-top:none;opacity:.5;transition:opacity .3s ease-in-out} +@container (min-width: 500px){ +.formeditor-element-validator:hover{-webkit-margin-end:0;margin-inline-end:0}} +typo3-form-form-element-stage-item[invalid] .formeditor-element-info-label{color:var(--typo3-text-color-danger)} +.formeditor-element:has(>[invalid]){--formeditor-stage-element-border-color:var(--typo3-state-danger-border-color);--formeditor-stage-element-hover-border-color:var(--typo3-state-danger-hover-border-color);--formeditor-stage-element-active-border-color:var(--typo3-state-danger-focus-border-color)} +.formeditor-sortable-handle{cursor:pointer} +.formeditor-sortable-ghost{outline:1px dashed var(--typo3-state-success-border-color)!important;outline-offset:-1px!important} +.formeditor-is-dragging .formeditor-new-element-placeholder{display:none} +.formeditor-new-element-placeholder{align-items:center;display:flex;justify-content:center;list-style:none} +.formeditor-new-element-container{align-items:center;border:var(--typo3-component-border-width) dashed color-mix(in srgb,transparent,currentColor 25%);border-radius:var(--typo3-component-border-radius);display:flex;justify-content:center;margin-top:var(--typo3-spacing);padding:.75rem .5rem} +.property-grid .form-control{min-width:auto} +.property-grid .table-fit{box-shadow:none;margin-bottom:0} +.property-grid-editor__entries{background-color:var(--typo3-component-border-color);border:var(--typo3-component-border-width) solid var(--typo3-component-border-color);border-radius:var(--typo3-component-border-radius);display:grid;gap:1px} +.property-grid-editor__entries+.property-grid-editor__actions{margin-top:calc(var(--typo3-spacing)/2)} +.property-grid-editor__entry{background-color:color-mix(in srgb,var(--typo3-component-bg),var(--typo3-component-color) 3%);display:flex;flex-direction:row;gap:var(--typo3-spacing);padding:var(--typo3-spacing);position:relative} +.property-grid-editor__entry:is(.dragging,.moving):after{border:2px dashed var(--typo3-state-primary-border-color);border-radius:calc(var(--typo3-component-border-radius) - var(--typo3-component-border-width));content:"";display:block;height:calc(100% - 2px);left:1px;position:absolute;top:1px;width:calc(100% - 2px)} +.property-grid-editor__entry-inputs{flex:1} +.property-grid-editor__entry-inputs div:last-child{margin-bottom:0} +.property-grid-editor__entry-buttons{display:flex;flex-direction:column;gap:.25rem} +.formeditor-module-viewmode-preview .formeditor-inspector-expand,.formeditor-module-viewmode-preview~.formeditor-inspector{display:none} +@media (min-width:950px){ +.formeditor-module-viewmode-preview~.formeditor-inspector{display:flex;transform:translateX(100%);-webkit-margin-start:calc(var(--formeditor-module-inspector)*-1 - var(--formeditor-module-gap));margin-inline-start:calc(var(--formeditor-module-inspector)*-1 - var(--formeditor-module-gap));opacity:0}} +.formeditor-module-viewmode-preview .formeditor-stage select[multiple=multiple]{height:auto;min-height:32px} +.formeditor-module-viewmode-preview .formeditor-stage textarea{min-height:100px} +.formeditor-module-viewmode-preview .formeditor-stage .container{width:auto} +.formeditor-module-viewmode-preview .formeditor-stage .form-navigation .btn-group button,.formeditor-module-viewmode-preview .formeditor-stage .form-navigation .btn-group span{display:inline-flex;-webkit-margin-end:1em;margin-inline-end:1em} +.formeditor-module-viewmode-preview .formeditor-stage .formeditor-element-preview{display:inline-block;position:relative;width:100%} +.formeditor-module-viewmode-preview .formeditor-stage .formeditor-new-element-container{display:none} +@media (min-width:950px){ +.formeditor-inner{align-items:flex-start;display:flex;gap:var(--formeditor-module-gap)} +.formeditor-stage-container{overflow:visible} +.formeditor-stage-container-inner{margin-inline:auto;max-width:800px} +.formeditor-inspector{border-radius:var(--formeditor-inspector-border-radius);flex-shrink:0;height:auto;inset:auto;max-height:calc(100dvh - var(--module-docheader-height) - var(--module-body-padding-y)*2);position:-webkit-sticky;position:sticky;top:calc(1rem + var(--module-docheader-bar-height));width:var(--formeditor-module-inspector);-webkit-border-end:var(--formeditor-inspector-border-width) solid var(--formeditor-inspector-border-color);border-inline-end:var(--formeditor-inspector-border-width) solid var(--formeditor-inspector-border-color);box-shadow:var(--formeditor-inspector-box-shadow);transform:none;transition:transform .3s ease-out,opacity .3s ease-out,margin .3s ease-out} +.formeditor-inspector-collapse,.formeditor-inspector-expand{display:none}} \ No newline at end of file diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg new file mode 100644 index 0000000..bcacef1 --- /dev/null +++ b/Resources/Public/Icons/Extension.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Resources/Public/JavaScript/backend/form-editor-tree-container.js b/Resources/Public/JavaScript/backend/form-editor-tree-container.js new file mode 100644 index 0000000..201eca3 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor-tree-container.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as c,html as f}from"lit";import{query as p,customElement as h}from"lit/decorators.js";import"@typo3/backend/tree/tree-toolbar.js";import"@typo3/form/backend/form-editor-tree.js";var l=function(i,e,t,n){var a=arguments.length,r=a<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,t):n,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(i,e,t,n);else for(var d=i.length-1;d>=0;d--)(s=i[d])&&(r=(a<3?s(r):a>3?s(e,t,r):s(e,t))||r);return a>3&&r&&Object.defineProperty(e,t,r),r};const m="typo3-backend-navigation-component-formeditortree";let o=class extends c{async setNodes(e){await this.updateComplete,this.tree&&this.tree.setNodes(e)}setSelectedNode(e){this.tree&&this.tree.setSelectedNode(e)}search(e){this.tree&&this.tree.search(e)}setNodeValidationError(e,t=!0){this.tree&&this.tree.setNodeValidationError(e,t)}setNodeChildHasError(e,t=!0){this.tree&&this.tree.setNodeChildHasError(e,t)}clearAllValidationErrors(){this.tree&&this.tree.clearAllValidationErrors()}createRenderRoot(){return this}render(){return f``}firstUpdated(){this.toolbar&&this.tree&&(this.toolbar.tree=this.tree),this.dispatchEvent(new CustomEvent("typo3:tree-container:ready",{bubbles:!0,composed:!0}))}};l([p("typo3-backend-navigation-component-formeditor-tree")],o.prototype,"tree",void 0),l([p("typo3-backend-tree-toolbar")],o.prototype,"toolbar",void 0),o=l([h("typo3-backend-navigation-component-formeditortree")],o);export{o as FormEditorTreeContainer,m as navigationComponentName}; diff --git a/Resources/Public/JavaScript/backend/form-editor-tree-events.js b/Resources/Public/JavaScript/backend/form-editor-tree-events.js new file mode 100644 index 0000000..c687725 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor-tree-events.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +const e={NODE_CLICKED:"typo3:form-editor-tree:node-clicked",NODE_EDIT:"typo3:form-editor-tree:node-edit",NODE_DELETE:"typo3:form-editor-tree:node-delete",DND_UPDATE:"typo3:form-editor-tree:dnd-update",DND_CHANGE:"typo3:form-editor-tree:dnd-change"};export{e as FORM_EDITOR_TREE_EVENTS}; diff --git a/Resources/Public/JavaScript/backend/form-editor-tree.js b/Resources/Public/JavaScript/backend/form-editor-tree.js new file mode 100644 index 0000000..8bb3c06 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor-tree.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{customElement as T}from"lit/decorators.js";import{Tree as _}from"@typo3/backend/tree/tree.js";import{TreeNodePositionEnum as d}from"@typo3/backend/tree/tree-node.js";import{DataTransferTypes as b}from"@typo3/backend/enum/data-transfer-types.js";import y from"@typo3/backend/severity.js";import{FORM_EDITOR_TREE_EVENTS as N}from"@typo3/form/backend/form-editor-tree-events.js";import g from"~labels/form.form_editor_javascript";var P=function(h,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(h,e,t,r);else for(var n=h.length-1;n>=0;n--)(a=h[n])&&(i=(s<3?a(i):s>3?a(e,t,i):a(e,t))||i);return s>3&&i&&Object.defineProperty(e,t,i),i};const w=0,I=1;let E=class extends _{constructor(){super(),this.nodeMetadata=new Map,this.validationErrors=new Set,this.childValidationErrors=new Set,this.settings.showIcons=!0,this.settings.defaultProperties={hasChildren:!1,nameSourceField:"label",type:"form_element",prefix:"",suffix:"",locked:!1,loaded:!0,overlayIcon:"",selectable:!0,expanded:!1,checked:!1},this.settings.dataUrl="",this.settings.filterUrl="",this.allowNodeEdit=!1,this.allowNodeDrag=!0,this.allowNodeSorting=!0}setNodes(e){this.syncExpandedStates(),this.nodeMetadata.clear();const t=this.convertToTreeNodes(e);this.nodes=this.enhanceNodes(t),this.applyValidationState(),this.requestUpdate()}setSelectedNode(e){const t=this.nodes.find(r=>r.identifier===e);t&&this.selectNode(t,!1)}setNodeValidationError(e,t=!0){t?this.validationErrors.add(e):this.validationErrors.delete(e),this.applyValidationState(),this.requestUpdate()}setNodeChildHasError(e,t=!0){t?this.childValidationErrors.add(e):this.childValidationErrors.delete(e),this.applyValidationState(),this.requestUpdate()}clearAllValidationErrors(){this.validationErrors.clear(),this.childValidationErrors.clear(),this.applyValidationState(),this.requestUpdate()}applyValidationState(){for(const e of this.nodes)e.statusInformation=[],e.overlayIcon=e.overlayIcon==="overlay-missing"?"":e.overlayIcon,this.validationErrors.has(e.identifier)?(e.overlayIcon="overlay-missing",e.statusInformation.push({label:g.get("formEditor.validation.hasError")||"Has validation errors",icon:"actions-exclamation-circle",overlayIcon:"",severity:y.error,priority:2})):this.childValidationErrors.has(e.identifier)&&e.statusInformation.push({label:g.get("formEditor.validation.childHasError")||"Contains elements with validation errors",icon:"actions-dot",overlayIcon:"",severity:y.warning,priority:1})}search(e){this.filter(e)}filter(e){if(typeof e=="string"&&(this.searchTerm=e),this.searchTerm){const t=this.searchTerm.toLowerCase();this.nodes.forEach(r=>{this.nodeMatchesSearchTerm(r,t)?(r.__hidden=!1,this.showParentNodes(r)):r.__hidden=!0})}else this.nodes.forEach(t=>{t.__hidden=!1});this.requestUpdate()}nodeMatchesSearchTerm(e,t){return e.name.toLowerCase().includes(t)||e.identifier.toLowerCase().includes(t)||e.note&&e.note.toLowerCase().includes(t)}async loadData(){this.loading=!1}async fetchData(){return[]}async loadChildren(e){e.loaded=!0}hideChildren(e){e.__expanded=!1,this.saveNodeStatus(e),this.dispatchEvent(new CustomEvent("typo3:tree:expand-toggle",{detail:{node:e}})),this.requestUpdate()}async showChildren(e){e.__expanded=!0,await this.loadChildren(e),this.saveNodeStatus(e),this.dispatchEvent(new CustomEvent("typo3:tree:expand-toggle",{detail:{node:e}})),this.requestUpdate()}selectNode(e,t=!0){super.selectNode(e,t),this.requestUpdate(),this.dispatchEvent(new CustomEvent("typo3:form-editor-tree:node-clicked",{detail:{identifierPath:e.identifier},bubbles:!0,composed:!0}))}async moveNode(e,t,r){const s=e.identifier,i=t.identifier,a=e.parentIdentifier,n=this.getParentNode(e);let l,o;r===d.INSIDE?(l=i,o=t):(l=t.parentIdentifier,o=this.getParentNode(t));const f=Array.from(this.nodes),c=f.indexOf(t);let p="",u="";r===d.BEFORE?(c>0&&(p=f[c-1].identifier),u=i):r===d.AFTER&&(p=i,c-1&&this.nodeMap.splice(v,1),e.parentIdentifier=l,o?e.depth=o.depth+1:e.depth=0,n&&this.getNodeChildren(n).length===0&&(n.hasChildren=!1,n.__expanded=!1),o&&(o.hasChildren||(o.hasChildren=!0,o.__expanded=!0),o.__expanded||await this.showChildren(o));let m=this.nodes.indexOf(t);(r===d.INSIDE||r===d.AFTER)&&m++,this.nodeMap.splice(m,0,e),this.requestUpdate(),D?this.dispatchEvent(new CustomEvent("typo3:form-editor-tree:dnd-change",{detail:{itemIdentifierPath:s,parentIdentifierPath:l,position:r,previousIdentifierPath:p,nextIdentifierPath:u},bubbles:!0,composed:!0})):this.dispatchEvent(new CustomEvent("typo3:form-editor-tree:dnd-update",{detail:{movedIdentifierPath:s,previousIdentifierPath:p,nextIdentifierPath:u},bubbles:!0,composed:!0}))}async firstUpdated(){await super.firstUpdated()}handleNodeDrop(e){const t=super.handleNodeDrop(e);return this.cleanDrag(),t&&(this.nodeDragMode=null,this.nodeDragPosition=null,this.refreshDragToolTip(),window.dispatchEvent(new DragEvent("dragend",{bubbles:!0,cancelable:!1}))),t}handleNodeDoubleClick(e,t){e.preventDefault(),e.stopPropagation(),this.dispatchFormEditorEvent(N.NODE_EDIT,{identifierPath:t.identifier,currentLabel:t.name})}handleNodeDelete(e){this.dispatchFormEditorEvent(N.NODE_DELETE,{identifierPath:e.identifier})}handleNodeMove(){}handleNodeDragStart(e,t){if(t.depth===0){e.preventDefault();return}super.handleNodeDragStart(e,t)}createDataTransferItemsFromNode(e){return[{type:b.treenode,data:this.getNodeTreeIdentifier(e)}]}handleNodeDragOver(e){if(!super.handleNodeDragOver(e))return!1;const r=this.getNodeFromDragEvent(e);return!r||!this.draggingNode?!1:this.isDropAllowedForFormEditor(this.draggingNode,r,this.nodeDragPosition)?!0:(this.nodeDragMode=null,this.nodeDragPosition=null,this.refreshDragToolTip(),this.cleanDrag(),!1)}isDropAllowedForFormEditor(e,t,r){if(e===t||e.depth===w)return!1;const s=this.getFormElementByNode(e);if(s?.isTopLevel&&r===d.INSIDE)return!1;const i=this.getTargetDepthAfterDrop(t,r);if(s?.isTopLevel&&i!==I)return!1;if(i===I){const a=this.getFormElementByNode(e);if(a&&!a.isTopLevel)return!1}if(r===d.INSIDE){const a=this.getFormElementByNode(t);if(a&&!a.isComposite||a?.isTopLevel&&s?.isTopLevel)return!1}return!this.isNodeDescendantOf(t,e)}getTargetDepthAfterDrop(e,t){return t===d.INSIDE?e.depth+1:e.depth}getFormElementByNode(e){const t=this.nodeMetadata.get(e.identifier);return t?{identifier:e.identifier,identifierPath:e.identifier,label:e.name,type:e.recordType,iconIdentifier:e.icon,isComposite:t.isComposite,isTopLevel:t.isTopLevel,enabled:!e.overlayIcon?.includes("hidden")}:null}isNodeDescendantOf(e,t){return e.__treeParents.includes(t.__treeIdentifier)}dispatchFormEditorEvent(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}syncExpandedStates(){this.nodes&&this.nodes.length>0&&this.nodes.forEach(e=>{this.saveNodeStatus(e)})}showParentNodes(e){e.__treeParents&&e.__treeParents.length>0&&e.__treeParents.forEach(t=>{const r=this.getNodeByTreeIdentifier(t);r&&(r.__hidden=!1,r.__expanded=!0)})}convertToTreeNodes(e,t="",r=0){const s=[];return e.forEach(i=>{this.nodeMetadata.set(i.identifierPath,{isComposite:i.isComposite,isTopLevel:i.isTopLevel});const a={type:"form_element",identifier:i.identifierPath,parentIdentifier:t,recordType:i.type,name:i.label,note:i.type?i.type:"",prefix:"",suffix:"",tooltip:`identifier=${i.identifier}`,depth:r,hasChildren:i.isComposite&&!!i.children&&i.children.length>0,loaded:!0,editable:!1,deletable:!1,icon:i.iconIdentifier,overlayIcon:i.enabled===!1?"overlay-hidden":"",statusInformation:[],labels:[],nameSourceField:"label",locked:!1,selectable:!0};if(s.push(a),i.children&&i.children.length>0){const n=this.convertToTreeNodes(i.children,i.identifierPath,r+1);s.push(...n)}}),s}};E=P([T("typo3-backend-navigation-component-formeditor-tree")],E);export{E as FormEditorTree}; diff --git a/Resources/Public/JavaScript/backend/form-editor.js b/Resources/Public/JavaScript/backend/form-editor.js new file mode 100644 index 0000000..39a9175 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor.js @@ -0,0 +1,16 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import y from"@typo3/backend/notification.js";import*as a from"@typo3/form/backend/form-editor/core.js";import{cloneDeep as d}from"lodash-es";import m from"~labels/form.form_editor_fail_safe_error_handling_javascript";const n=a.assert;class c{constructor(t,e,r){this.isRunning=!1,this.unsavedContent=!1,this.configuration=t||{},this.mediator=e,this.viewModel=r}getPublisherSubscriber(){return a.getPublisherSubscriber()}undoApplicationState(){this.getApplicationStateStack().incrementCurrentStackPointer()}redoApplicationState(){this.getApplicationStateStack().decrementCurrentStackPointer()}getMaximalApplicationStates(){return this.getApplicationStateStack().getMaximalStackSize()}getCurrentApplicationStates(){return this.getApplicationStateStack().getCurrentStackSize()}getCurrentApplicationStatePosition(){return this.getApplicationStateStack().getCurrentStackPointer()}setFormDefinition(t){n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "formDefinition"',1519855175),this.getApplicationStateStack().setCurrentState("formDefinition",this.getFactory().createFormElement(t,void 0,void 0,!0))}getRunningAjaxRequest(t){return n(this.getUtility().isNonEmptyString(t),'Invalid parameter "type"',1475378543),a.getRunningAjaxRequest(t)}getUtility(){return a.getUtility()}assert(t,e,r){this.getUtility().assert(t,e,r)}buildPropertyPath(t,e,r,i,o){this.getUtility().isUndefinedOrNull(i)&&(i=this.getCurrentlySelectedFormElement());const l=this.getRepository().findFormElement(i);return this.getUtility().buildPropertyPath(t,e,r,l,o)}addPropertyValidationValidator(t,e){this.getPropertyValidationService().addValidator(t,e)}validateCurrentlySelectedFormElementProperty(t){return this.validateFormElementProperty(this.getCurrentlySelectedFormElement(),t)}validateFormElementProperty(t,e){const r=this.getRepository().findFormElement(t);return this.getPropertyValidationService().validateFormElementProperty(r,e)}validateFormElement(t){const e=this.getRepository().findFormElement(t);return this.getPropertyValidationService().validateFormElement(e)}validationResultsHasErrors(t){return this.getPropertyValidationService().validationResultsHasErrors(t)}validateFormElementRecursive(t,e){const r=this.getRepository().findFormElement(t);return this.getPropertyValidationService().validateFormElementRecursive(r,e)}setUnsavedContent(t){n(typeof t=="boolean",'Invalid parameter "unsavedContent"',1475378544),this.unsavedContent=t}getUnsavedContent(){return this.unsavedContent}getRootFormElement(){return this.getRepository().getRootFormElement()}getCurrentlySelectedFormElement(){return this.getRepository().findFormElementByIdentifierPath(this.getApplicationStateStack().getCurrentState("currentlySelectedFormElementIdentifierPath"))}setCurrentlySelectedFormElement(t,e){e=!!e;const r=this.getRepository().findFormElement(t);this.getApplicationStateStack().setCurrentState("currentlySelectedFormElementIdentifierPath",r.get("__identifierPath")),e||this.refreshCurrentlySelectedPageIndex(),this.getPublisherSubscriber().publish("core/currentlySelectedFormElementChanged",[r])}getFormElementByIdentifierPath(t){return n(this.getUtility().isNonEmptyString(t),'Invalid parameter "identifierPath"',1475378545),this.getRepository().findFormElementByIdentifierPath(t)}isFormElementIdentifierUsed(t){return this.getRepository().isFormElementIdentifierUsed(t)}createAndAddFormElement(t,e,r){const i=this.addFormElement(this.createFormElement(t,r),e,r);return i.set("renderables",i.get("renderables")),i}addFormElement(t,e,r){this.saveApplicationState(),this.getUtility().isUndefinedOrNull(e)&&(e=this.getCurrentlySelectedFormElement());const i=this.getRepository().findFormElement(e);return n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "formElement"',1475434337),this.getRepository().addFormElement(t,i,!0,r)}createFormElement(t,e){n(this.getUtility().isNonEmptyString(t),'Invalid parameter "formElementType"',1475434336);const r=this.getRepository().getNextFreeFormElementIdentifier(t),i=this.getFormElementDefinitionByType(t,void 0);return this.getFactory().createFormElement({type:t,identifier:r,label:i.label||t},void 0,void 0,void 0,e)}removeFormElement(t,e){this.saveApplicationState();const r=this.getRepository().findFormElement(t),i=r.get("__parentRenderable");return this.getRepository().removeFormElement(r,!0,e),i}moveFormElement(t,e,r,i){this.saveApplicationState();let o=this.getRepository().findFormElement(t);const l=this.getRepository().findFormElement(r);return n(e==="after"||e==="before"||e==="inside",'Invalid position "'+e+'"',1475378551),o=this.getRepository().moveFormElement(o,e,l,!0),i=!!i,i||o.get("__parentRenderable").set("renderables",o.get("__parentRenderable").get("renderables")),o}getPropertyCollectionElementConfiguration(t,e,r){let i,o;this.getUtility().isUndefinedOrNull(r)&&(r=this.getCurrentlySelectedFormElement());const l=this.getRepository().findFormElement(r);n(this.getUtility().isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1475378555),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1475378556);const p=this.getFormElementDefinitionByType(l.get("type"),void 0);return this.getUtility().isUndefinedOrNull(p.propertyCollections)?{}:(i=p.propertyCollections[e],n(!this.getUtility().isUndefinedOrNull(i),'Invalid collection name "'+e+'"',1475446108),o=this.getRepository().findCollectionElementByIdentifierPath(t,i),d(o))}getIndexFromPropertyCollectionElement(t,e,r){this.getUtility().isUndefinedOrNull(r)&&(r=this.getCurrentlySelectedFormElement());const i=this.getRepository().findFormElement(r);return n(this.getUtility().isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1475378557),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1475378558),this.getRepository().getIndexFromPropertyCollectionElementByIdentifier(t,e,i)}createAndAddPropertyCollectionElement(t,e,r,i,o){return this.addPropertyCollectionElement(this.createPropertyCollectionElement(t,e,i),e,r,o)}addPropertyCollectionElement(t,e,r,i){let o;this.saveApplicationState(),this.getUtility().isUndefinedOrNull(r)&&(r=this.getCurrentlySelectedFormElement());const l=this.getRepository().findFormElement(r);return n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "collectionElement"',1475443301),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1475443300),this.getUtility().isUndefinedOrNull(i)&&(o=l.get(e),Array.isArray(o)&&o.length>0&&(i=o[o.length-1].identifier)),this.getRepository().addPropertyCollectionElement(t,e,l,i,!1)}createPropertyCollectionElement(t,e,r){return n(this.getUtility().isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1475378559),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1475378560),(typeof r!="object"||r===null||Array.isArray(r))&&(r={}),this.getFactory().createPropertyCollectionElement(t,r,e)}removePropertyCollectionElement(t,e,r,i){this.saveApplicationState(),this.getUtility().isUndefinedOrNull(r)&&(r=this.getCurrentlySelectedFormElement());const o=this.getRepository().findFormElement(r);n(this.getUtility().isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1475378561),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "collectionName"',1475378562),this.getRepository().removePropertyCollectionElementByIdentifier(o,t,e,!0),i=!!i,i||this.getPublisherSubscriber().publish("core/formElement/somePropertyChanged",["__fakeProperty"])}movePropertyCollectionElement(t,e,r,i,o,l){this.saveApplicationState(),o=this.getRepository().findFormElement(o),n(typeof t=="string",'Invalid parameter "collectionElementToMove"',1477404352),n(typeof r=="string",'Invalid parameter "referenceCollectionElement"',1477404353),n(e==="after"||e==="before",'Invalid position "'+e+'"',1477404354),n(this.getUtility().isNonEmptyString(i),'Invalid parameter "collectionName"',1477404355),this.getRepository().movePropertyCollectionElement(t,e,r,i,o,l)}getFormElementDefinitionByType(t,e){n(this.getUtility().isNonEmptyString(t),'Invalid parameter "elementType"',1475378563);const r=this.getRepository().getFormEditorDefinition("formElements",t);if(e!==void 0){const i=r[e];return i!==null&&typeof i=="object"?d(i):i}return r!==null&&typeof r=="object"?d(r):r}getFormElementDefinition(t,e){return t=this.getRepository().findFormElement(t),this.getFormElementDefinitionByType(t.get("type"),e)}getFormEditorDefinition(t,e){return this.getRepository().getFormEditorDefinition(t,e)}getFormElementPropertyValidatorDefinition(t){n(this.getUtility().isNonEmptyString(t),'Invalid parameter "validatorIdentifier"',1475672362);const e=this.getRepository().getFormEditorDefinition("formElementPropertyValidators",t);return d(e)}getCurrentlySelectedPageIndex(){return this.getApplicationStateStack().getCurrentState("currentlySelectedPageIndex")}refreshCurrentlySelectedPageIndex(){this.getApplicationStateStack().setCurrentState("currentlySelectedPageIndex",this.getPageIndexFromFormElement(this.getCurrentlySelectedFormElement()))}getCurrentlySelectedPage(){const t=this.getRepository().getRootFormElement().get("renderables")[this.getCurrentlySelectedPageIndex()];return n(typeof t=="object"&&t!==null&&!Array.isArray(t),"No page found",1477786068),t}getLastTopLevelElementOnCurrentPage(){const t=this.getCurrentlySelectedPage().get("renderables");if(!this.getUtility().isUndefinedOrNull(t))return t[t.length-1]}getLastFormElementWithinParentFormElement(t){return t=this.getRepository().findFormElement(t),t.get("__identifierPath")===this.getRootFormElement().get("__identifierPath")?t:t.get("__parentRenderable").get("renderables")[t.get("__parentRenderable").get("renderables").length-1]}getPageIndexFromFormElement(t){return t=this.getRepository().findFormElement(t),this.getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(t)}renderCurrentFormPage(){this.renderFormPage(this.getCurrentlySelectedPageIndex())}renderFormPage(t){n(typeof t=="number",'Invalid parameter "pageIndex"',1475446442),this.getDataBackend().renderFormDefinitionPage(t)}findEnclosingCompositeFormElementWhichIsNotOnTopLevel(t){return this.getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(this.getRepository().findFormElement(t))}findEnclosingGridRowFormElement(t){return this.getRepository().findEnclosingGridRowFormElement(this.getRepository().findFormElement(t))}getNonCompositeNonToplevelFormElements(){return this.getRepository().getNonCompositeNonToplevelFormElements()}isRootFormElementSelected(){return this.getCurrentlySelectedFormElement().get("__identifierPath")===this.getRootFormElement().get("__identifierPath")}getViewModel(){return this.viewModel}saveFormDefinition(){this.getDataBackend().saveFormDefinition()}run(){if(this.isRunning)throw"You can not run the app twice (1473200696)";try{this.bootstrap(),this.isRunning=!0}catch(t){if(!(t instanceof Error))throw t;console.error("Form editor error:",t),y.error(m.get("formEditor.error.headline"),m.get("formEditor.error.message")+`\r +\r +`+m.get("formEditor.error.technicalReason")+`\r +`+t.message)}return this}saveApplicationState(){this.getApplicationStateStack().addAndReset({formDefinition:this.getApplicationStateStack().getCurrentState("formDefinition").clone(),currentlySelectedPageIndex:this.getApplicationStateStack().getCurrentState("currentlySelectedPageIndex"),currentlySelectedFormElementIdentifierPath:this.getApplicationStateStack().getCurrentState("currentlySelectedFormElementIdentifierPath")})}getDataBackend(){return a.getDataBackend()}getFactory(){return a.getFactory()}getRepository(){return a.getRepository()}getPropertyValidationService(){return a.getPropertyValidationService()}getApplicationStateStack(){return a.getApplicationStateStack()}dataBackendSetup(t,e,r){n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "endpoints"',1475379748),n(this.getUtility().isNonEmptyString(e),'Invalid parameter "prototypeName"',1475927876),n(this.getUtility().isNonEmptyString(r),'Invalid parameter "formPersistenceIdentifier"',1475379749),a.getDataBackend().setEndpoints(t),a.getDataBackend().setPrototypeName(e),a.getDataBackend().setPersistenceIdentifier(r)}repositorySetup(t){n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "formEditorDefinitions"',1475379750),this.getRepository().setFormEditorDefinitions(t)}viewSetup(t){n(typeof this.viewModel.bootstrap=="function",'The view model does not implement the method "bootstrap"',1475492374),this.getUtility().isUndefinedOrNull(t)&&(t=[]),this.viewModel.bootstrap(s,t)}mediatorSetup(){n(typeof this.mediator.bootstrap=="function",'The mediator does not implement the method "bootstrap"',1475492032),this.mediator.bootstrap(s,this.viewModel)}applicationStateStackSetup(t,e){n(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "rootFormElement"',1475379751),typeof e!="number"&&(e=10),this.getApplicationStateStack().setMaximalStackSize(e),this.getApplicationStateStack().addAndReset({currentlySelectedPageIndex:0,currentlySelectedFormElementIdentifierPath:t.identifier},!0),this.getApplicationStateStack().setCurrentState("formDefinition",this.getFactory().createFormElement(t,void 0,void 0,!0))}bootstrap(){this.mediatorSetup(),this.dataBackendSetup(this.configuration.endpoints,this.configuration.prototypeName,this.configuration.formPersistenceIdentifier),this.repositorySetup(this.configuration.formEditorDefinitions),this.applicationStateStackSetup(this.configuration.formDefinition,this.configuration.maximumUndoSteps),this.setCurrentlySelectedFormElement(this.getRepository().getRootFormElement()),this.viewSetup(this.configuration.additionalViewModelModules)}}let s=null;function h(g,t,e){return s===null&&(s=new c(g,t,e)),s}export{c as FormEditor,h as getInstance}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/date-editor.js b/Resources/Public/JavaScript/backend/form-editor/component/date-editor.js new file mode 100644 index 0000000..477a1de --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/date-editor.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as v,html as d,nothing as p}from"lit";import{property as g,state as r,customElement as $}from"lit/decorators.js";import o from"~labels/form.relative_date_editor";var n=function(u,t,e,s){var h=arguments.length,a=h<3?t:s===null?s=Object.getOwnPropertyDescriptor(t,e):s,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(u,t,e,s);else for(var m=u.length-1;m>=0;m--)(l=u[m])&&(a=(h<3?l(a):h>3?l(t,e,a):l(t,e))||a);return h>3&&a&&Object.defineProperty(t,e,a),a};class c extends Event{static{this.eventName="typo3:backend:form-editor:component:date-editor:change"}constructor(t){super(c.eventName),this.value=t}}let i=class extends v{constructor(){super(...arguments),this.mode="no",this.absoluteDate="",this.direction="-",this.amount=0,this.unit="years",this.customValue="",this.value="",this._absoluteDateRegex=null}get absoluteDateRegex(){return this._absoluteDateRegex||(this._absoluteDateRegex=new RegExp(this.absolutePattern)),this._absoluteDateRegex}firstUpdated(){if(!this.absolutePattern)throw new Error("typo3-form-date-editor: absolute-pattern attribute is required.");this.parseValue(this.value)}createRenderRoot(){return this}render(){return d`
${this.mode==="absolute"?this.renderAbsolute():p} ${this.mode==="relative"?this.renderRelative():p} ${this.mode==="custom"?this.renderCustom():p}`}renderAbsolute(){return d`
`}renderRelative(){return d`
`}renderCustom(){return d`
`}parseValue(t){if(!t){this.mode="no";return}if(t.toLowerCase()==="today"){this.mode="today";return}if(this.absoluteDateRegex.test(t)){this.mode="absolute",this.absoluteDate=t;return}const e=t.match(/^([+-]?)\s*(\d+)\s+(days?|weeks?|months?|years?)$/i);if(e){this.mode="relative",this.direction=e[1]==="+"?"+":"-",this.amount=parseInt(e[2],10);const s=e[3].toLowerCase();this.unit=s.endsWith("s")?s:`${s}s`;return}this.mode="custom",this.customValue=t}composeValue(){switch(this.mode){case"today":return"today";case"absolute":return this.absoluteDate;case"relative":return this.amount===0?"":`${this.direction}${this.amount} ${this.unit}`;case"custom":return this.customValue.trim();default:return""}}emitChange(){const t=this.composeValue();this.value=t,this.dispatchEvent(new c(t))}handleModeChange(t){const e=t.target.value;if(e==="custom"&&this.mode==="relative"){const s=this.composeValue();s&&(this.customValue=s)}this.mode=e,this.mode==="relative"&&this.amount===0&&(this.amount=1),this.emitChange()}handleAbsoluteChange(t){this.absoluteDate=t.target.value,this.emitChange()}handleDirectionChange(t){this.direction=t.target.value,this.emitChange()}handleAmountChange(t){this.amount=parseInt(t.target.value,10)||0,this.emitChange()}handleUnitChange(t){this.unit=t.target.value,this.emitChange()}handleCustomChange(t){this.customValue=t.target.value,this.emitChange()}};n([g({type:String,attribute:"absolute-pattern"})],i.prototype,"absolutePattern",void 0),n([r()],i.prototype,"mode",void 0),n([r()],i.prototype,"absoluteDate",void 0),n([r()],i.prototype,"direction",void 0),n([r()],i.prototype,"amount",void 0),n([r()],i.prototype,"unit",void 0),n([r()],i.prototype,"customValue",void 0),i=n([$("typo3-form-date-editor")],i);export{i as DateEditor,c as DateEditorChangeEvent}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/form-element-selector.js b/Resources/Public/JavaScript/backend/form-editor/component/form-element-selector.js new file mode 100644 index 0000000..203ebad --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/form-element-selector.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{property as m,customElement as u}from"lit/decorators.js";import{LitElement as f,html as p,nothing as b}from"lit";var d=function(r,e,n,i){var s=arguments.length,t=s<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,n):i,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(r,e,n,i);else for(var c=r.length-1;c>=0;c--)(l=r[c])&&(t=(s<3?l(t):s>3?l(e,n,t):l(e,n))||t);return s>3&&t&&Object.defineProperty(e,n,t),t};class a extends Event{static{this.eventName="typo3:backend:form-editor:component:form-element-selector:selected"}constructor(e){super(a.eventName),this.value=e}}let o=class extends f{constructor(){super(...arguments),this.elements=[],this.size=""}createRenderRoot(){return this}render(){return this.elements?.length?p` `:p`${b}`}renderEntry(e){return p`
  • this.onSelect(e.value)} href=# class=dropdown-item data-formelement-identifier=${e.value}> ${e.label}
  • `}onSelect(e){this.dispatchEvent(new a(e))}};d([m({type:Array,attribute:"elements"})],o.prototype,"elements",void 0),d([m({type:String})],o.prototype,"size",void 0),o=d([u("typo3-form-element-selector")],o);export{o as FormElementSelector,a as FormElementSelectorSelectedEvent}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item-toolbar.js b/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item-toolbar.js new file mode 100644 index 0000000..b741f20 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item-toolbar.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as f,nothing as b,html as p}from"lit";import{property as n,customElement as v}from"lit/decorators.js";import c from"~labels/form.form_editor_javascript";import"@typo3/backend/element/icon-element.js";var o=function(l,e,r,a){var s=arguments.length,i=s<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,r):a,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(l,e,r,a);else for(var m=l.length-1;m>=0;m--)(d=l[m])&&(i=(s<3?d(i):s>3?d(e,r,i):d(e,r))||i);return s>3&&i&&Object.defineProperty(e,r,i),i};let t=class extends f{constructor(){super(...arguments),this.active=!1,this.iconIdentifier="",this.elementType="",this.elementIdentifier="",this.isHidden=!1,this.isInvalid=!1}createRenderRoot(){return this}render(){return this.active?p`
    ${this.elementType}
    `:b}handleNewElementBefore(e){e.preventDefault(),this.dispatchEvent(new CustomEvent("toolbar-new-element-before",{bubbles:!0,composed:!0}))}handleNewElementAfter(e){e.preventDefault(),this.dispatchEvent(new CustomEvent("toolbar-new-element-after",{bubbles:!0,composed:!0}))}handleRemoveElement(e){e.preventDefault(),this.dispatchEvent(new CustomEvent("toolbar-remove-element",{bubbles:!0,composed:!0}))}};o([n({type:Boolean,reflect:!0})],t.prototype,"active",void 0),o([n({type:String,attribute:"icon-identifier"})],t.prototype,"iconIdentifier",void 0),o([n({type:String,attribute:"element-type"})],t.prototype,"elementType",void 0),o([n({type:String,attribute:"element-identifier"})],t.prototype,"elementIdentifier",void 0),o([n({type:Boolean,attribute:"is-hidden"})],t.prototype,"isHidden",void 0),o([n({type:Boolean,attribute:"is-invalid"})],t.prototype,"isInvalid",void 0),t=o([v("typo3-form-form-element-stage-item-toolbar")],t);export{t as FormElementStageItemToolbar}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item.js b/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item.js new file mode 100644 index 0000000..9a7a911 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/form-element-stage-item.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as c,html as s,nothing as f}from"lit";import{property as n,customElement as u}from"lit/decorators.js";import"@typo3/backend/element/icon-element.js";import"@typo3/form/backend/form-editor/component/form-element-stage-item-toolbar.js";import{stripTags as v}from"@typo3/form/backend/form-editor/utility/string-utility.js";var o=function(d,e,i,r){var a=arguments.length,l=a<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,i):r,m;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(d,e,i,r);else for(var p=d.length-1;p>=0;p--)(m=d[p])&&(l=(a<3?m(l):a>3?m(e,i,l):m(e,i))||l);return a>3&&l&&Object.defineProperty(e,i,l),l};let t=class extends c{constructor(){super(...arguments),this.elementType="",this.elementIdentifier="",this.elementLabel="",this.elementIconIdentifier="",this.isRequired=!1,this.isHidden=!1,this.invalid=!1,this.validators=[],this.options=[]}createRenderRoot(){return this}render(){return s`
    ${v(this.elementLabel)} ${this.isRequired?s`*`:f}
    ${this.renderInfoContent()}
    ${this.renderValidators()}
    `}renderInfoContent(){const e=this.renderContentItems();return e.length?s`
    ${e}
    `:f}renderContentItems(){const e=[];if(this.content&&e.push(s`
    ${v(this.content)}
    `),this.options?.length){const i=this.options.map(r=>({label:r.label,className:r.selected?"selected":void 0}));e.push(this.renderMultivalue(i))}if(this.allowedMimeTypes?.length){const i=this.allowedMimeTypes.map(r=>({label:r}));e.push(this.renderMultivalue(i))}return e}renderMultivalue(e){return s`
    ${e.map(i=>s`
    ${i.label}
    `)}
    `}renderValidators(){return this.validators?.length?s`
    ${this.validators.map(e=>s`
    ${e.label}
    `)}
    `:f}};o([n({type:String,attribute:"element-type"})],t.prototype,"elementType",void 0),o([n({type:String,attribute:"element-identifier"})],t.prototype,"elementIdentifier",void 0),o([n({type:String,attribute:"element-label"})],t.prototype,"elementLabel",void 0),o([n({type:String,attribute:"element-icon-identifier"})],t.prototype,"elementIconIdentifier",void 0),o([n({type:Boolean,attribute:"is-required"})],t.prototype,"isRequired",void 0),o([n({type:Boolean,attribute:"is-hidden"})],t.prototype,"isHidden",void 0),o([n({type:Boolean,reflect:!0})],t.prototype,"invalid",void 0),o([n({type:Array})],t.prototype,"validators",void 0),o([n({type:Array})],t.prototype,"options",void 0),o([n({type:Array})],t.prototype,"allowedMimeTypes",void 0),o([n({type:String})],t.prototype,"content",void 0),t=o([u("typo3-form-form-element-stage-item")],t);export{t as FormElementStageItem}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/page-stage-item.js b/Resources/Public/JavaScript/backend/form-editor/component/page-stage-item.js new file mode 100644 index 0000000..d393b27 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/page-stage-item.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as f,html as c}from"lit";import{property as s,customElement as g}from"lit/decorators.js";import u from"~labels/form.form_editor_javascript";var a=function(o,e,r,p){var i=arguments.length,t=i<3?e:p===null?p=Object.getOwnPropertyDescriptor(e,r):p,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(o,e,r,p);else for(var m=o.length-1;m>=0;m--)(l=o[m])&&(t=(i<3?l(t):i>3?l(e,r,t):l(e,r))||t);return i>3&&t&&Object.defineProperty(e,r,t),t};let n=class extends f{constructor(){super(...arguments),this.pageTitle=""}createRenderRoot(){return this}render(){const e=this.pageTitle||u.get("formEditor.step.name.empty");return c`

    ${e}

    `}};a([s({type:String,attribute:"page-title"})],n.prototype,"pageTitle",void 0),n=a([g("typo3-form-page-stage-item")],n);export{n as PageStageItem}; diff --git a/Resources/Public/JavaScript/backend/form-editor/component/property-grid-editor.js b/Resources/Public/JavaScript/backend/form-editor/component/property-grid-editor.js new file mode 100644 index 0000000..9024963 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/component/property-grid-editor.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{LitElement as f,html as d,nothing as h}from"lit";import{repeat as v}from"lit/directives/repeat.js";import{classMap as g}from"lit/directives/class-map.js";import{live as b}from"lit/directives/live.js";import{property as s,state as u,customElement as y}from"lit/decorators.js";import"@typo3/backend/element/icon-element.js";import"@typo3/form/backend/form-editor/component/form-element-selector.js";var a=function(p,e,t,l){var i=arguments.length,o=i<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,t):l,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(p,e,t,l);else for(var c=p.length-1;c>=0;c--)(r=p[c])&&(o=(i<3?r(o):i>3?r(e,t,o):r(e,t))||o);return i>3&&o&&Object.defineProperty(e,t,o),o};class m extends Event{static{this.eventName="typo3:backend:form-editor:component:property-grid-editor:update"}constructor(e){super(m.eventName),this.data=e}}let n=class extends f{constructor(){super(...arguments),this.entries=[],this.formElements=[],this.labelLabel="Label",this.labelValue="Value",this.labelSelected="Selected",this.labelAdd="Add",this.labelRemove="Remove",this.labelMove="Move",this.enableAddRow=!1,this.enableDeleteRow=!1,this.enableSelection=!0,this.enableMultiSelection=!1,this.enableSorting=!1,this.enableLabelAsFallbackValue=!1,this.enableLabelFormElementSelectionButton=!1,this.enableValueFormElementSelectionButton=!1,this.draggedEntry=null,this.movedEntry=null,this.activeElementRef=null}createRenderRoot(){return this}updated(e){if(this.activeElementRef&&(this.activeElementRef.focus(),this.activeElementRef=null),e.has("entries")){const t=e.get("entries");t!==void 0&&JSON.stringify(t)!==JSON.stringify(this.entries)&&this.dispatchEvent(new m(this.entries))}}render(){return d`
    ${this.entries?.length?d`
    ${v(this.entries,e=>e.id,e=>this.renderEntry(e))}
    `:h} ${this.enableAddRow?d`
    `:h}
    `}renderEntry(e){return d`
    this.handleDragOver(t)} @dragenter=${t=>this.handleDragEnter(t,e)} @drop=${t=>this.handleDrop(t)} @dragend=${t=>this.handleDragEnd(t)}>
    this.handleChange(t,"label",e)} @keyup=${t=>this.handleChange(t,"label",e)} @focusout=${()=>this.handleFocusOut(e)} .value=${b(e.label)}> ${this.renderFormElementSelectionButton(this.enableLabelFormElementSelectionButton,"label",e)}
    this.handleChange(t,"value",e)} @keyup=${t=>this.handleChange(t,"value",e)} .value=${b(e.value)}> ${this.renderFormElementSelectionButton(this.enableValueFormElementSelectionButton,"value",e)}
    ${this.enableSelection||this.enableMultiSelection?d`
    this.handleChange(t,"selected",e)} .checked=${b(e.selected)}>
    `:h}
    ${this.enableSorting||this.enableDeleteRow?d`
    ${this.enableSorting?d``:h} ${this.enableDeleteRow?d``:h}
    `:h}
    `}renderFormElementSelectionButton(e,t,l){return!e||!this.formElements?.length?d`${h}`:d`this.handleFormElementSelection(i,t,l)} elements=${JSON.stringify(this.formElements)} size=small>`}handleFormElementSelection(e,t,l){const i=l[t];i?this.setEntryProperty(l,t,`${i} {${e.value}}`):this.setEntryProperty(l,t,`{${e.value}}`)}handleFocusOut(e){this.enableLabelAsFallbackValue&&e.value===""&&this.setEntryProperty(e,"value",e.label)}handleChange(e,t,l){const i=e.target,o=i.type==="checkbox"?i.checked:i.value;this.setEntryProperty(l,t,o)}handleRemove(e){this.entries=this.entries.filter(t=>t!==e)}handleCreate(){const e={id:"fe"+Math.floor(Math.random()*42)+Date.now(),label:"",value:"",selected:!1};this.entries=[...this.entries,e]}handleDragStart(e,t){e.stopImmediatePropagation(),this.draggedEntry=t,e.dataTransfer?.setData("text/plain","dragging"),e.dataTransfer?.setDragImage(new Image,0,0)}handleDragOver(e){e.preventDefault(),e.stopImmediatePropagation()}handleDragEnter(e,t){if(e.preventDefault(),e.stopImmediatePropagation(),!this.draggedEntry||this.draggedEntry===t)return;const l=[...this.entries],i=l.indexOf(this.draggedEntry),o=l.indexOf(t);l.splice(i,1);const r=(i=i.length)return;i.splice(o,1);const c=(oc===i?o:{...r,selected:!1});return}this.entries=this.entries.map((r,c)=>c===i?o:r)}};a([s({type:Array,attribute:"entries"})],n.prototype,"entries",void 0),a([s({type:Array,attribute:"form-elements"})],n.prototype,"formElements",void 0),a([s({type:String,attribute:"label-label"})],n.prototype,"labelLabel",void 0),a([s({type:String,attribute:"label-value"})],n.prototype,"labelValue",void 0),a([s({type:String,attribute:"label-selected"})],n.prototype,"labelSelected",void 0),a([s({type:String,attribute:"label-add"})],n.prototype,"labelAdd",void 0),a([s({type:String,attribute:"label-remove"})],n.prototype,"labelRemove",void 0),a([s({type:String,attribute:"label-move"})],n.prototype,"labelMove",void 0),a([s({type:Boolean})],n.prototype,"enableAddRow",void 0),a([s({type:Boolean})],n.prototype,"enableDeleteRow",void 0),a([s({type:Boolean})],n.prototype,"enableSelection",void 0),a([s({type:Boolean})],n.prototype,"enableMultiSelection",void 0),a([s({type:Boolean})],n.prototype,"enableSorting",void 0),a([s({type:Boolean})],n.prototype,"enableLabelAsFallbackValue",void 0),a([s({type:Boolean})],n.prototype,"enableLabelFormElementSelectionButton",void 0),a([s({type:Boolean})],n.prototype,"enableValueFormElementSelectionButton",void 0),a([u()],n.prototype,"draggedEntry",void 0),a([u()],n.prototype,"movedEntry",void 0),n=a([y("typo3-form-property-grid-editor")],n);export{n as PropertyGridEditor,m as PropertyGridEditorUpdateEvent}; diff --git a/Resources/Public/JavaScript/backend/form-editor/core.js b/Resources/Public/JavaScript/backend/form-editor/core.js new file mode 100644 index 0000000..de0b17a --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/core.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import D from"@typo3/core/ajax/ajax-request.js";import{AjaxResponse as P}from"@typo3/core/ajax/ajax-response.js";import{cloneDeep as R}from"lodash-es";function a(c,e,t){if(typeof c=="function"&&(c=c()!==!1),!c)throw e=e||"Assertion failed",t&&(e=e+" ("+t+")"),typeof Error<"u"?new Error(e):e}class O{assert(e,t,r){a(e,t,r)}isUndefinedOrNull(e){return e==null}isNonEmptyArray(e){return Array.isArray(e)&&e.length>0}isNonEmptyString(e){return typeof e=="string"&&e.length>0}canBeInterpretedAsInteger(e){if(typeof e=="number")return!0;if(typeof e!="string")return!1;const t=e;return(t*1).toString()===t.toString()&&t.toString().indexOf(".")===-1}buildPropertyPath(e,t,r,i,n){let o="";return n=!!n,this.isNonEmptyString(t)||this.isNonEmptyString(r)?(a(this.isNonEmptyString(t),'Invalid parameter "collectionElementIdentifier"',1475412569),a(this.isNonEmptyString(r),'Invalid parameter "collectionName"',1475412570),o=r+"."+C.getIndexFromPropertyCollectionElementByIdentifier(t,r,i)):o="",this.isUndefinedOrNull(e)||(a(this.isNonEmptyString(e),'Invalid parameter "propertyPath"',1475415988),this.isNonEmptyString(o)?o=o+"."+e:o=e),n||a(this.isNonEmptyString(o),"The property path could not be resolved",1475663210),o}convertToSimpleObject(e){a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1475377782);const t={},r="getObjectData"in e&&typeof e.getObjectData=="function"?e.getObjectData():e,i=r.renderables;delete r.renderables;for(const[n,o]of Object.entries(r))n.match(/^__/)||(o!==null&&typeof o=="object"&&!Array.isArray(o)?t[n]=this.convertToSimpleObject(o):typeof o!="function"&&typeof o<"u"&&(t[n]=o));if(Array.isArray(i)){t.renderables=[];for(let n=0,o=i.length;n-1||(i[o]=n[r][o]);n[r]=i,u().setCurrentState("propertyValidationServiceRegisteredValidators",n)}removeAllValidatorIdentifiersFromFormElement(e){a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1475668189);const t={},r=u().getCurrentState("propertyValidationServiceRegisteredValidators");for(const i of Object.keys(r||{}))i===e.get("__identifierPath")||i.indexOf(e.get("__identifierPath")+"/")>-1||(t[i]=r[i]);u().setCurrentState("propertyValidationServiceRegisteredValidators",t)}addValidator(e,t){a(l.isNonEmptyString(e),'Invalid parameter "validatorIdentifier"',1475669143),a(typeof t=="function",'Invalid parameter "func"',1475669144),a(typeof this.validators[e]!="function",'The validator "'+e+'" is already registered',1475669145),this.validators[e]=t}validateFormElementProperty(e,t){let r;a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1475676517),a(l.isNonEmptyString(t),'Invalid parameter "propertyPath"',1475676518);const i=e.get("__identifierPath"),n=[],o=u().getCurrentState("propertyValidationServiceRegisteredValidators");if(r={propertyValidatorsMode:"AND"},!l.isUndefinedOrNull(o[i])&&typeof o[i][t]=="object"&&o[i][t]!==null&&!Array.isArray(o[i][t])&&Array.isArray(o[i][t].validators)){r=o[i][t].configuration;const s=o[i][t].validators,d=[],p=[];let y=0;for(let I=0,h=s.length;I0&&d.length!==y||n.push(...d),n.push(...p)}return n}validateFormElement(e){a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1475749668);const t=e.get("__identifierPath"),r=[],i=u().getCurrentState("propertyValidationServiceRegisteredValidators");if(!l.isUndefinedOrNull(i[t]))for(const n of Object.keys(i[t]))r.push({propertyPath:n,validationResults:this.validateFormElementProperty(e,n)});return r}validationResultsHasErrors(e){a(Array.isArray(e),'Invalid parameter "validationResults"',1478613477);for(let t=0,r=e.length;t0)return!0;return!1}validateFormElementRecursive(e,t,r){if(a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1475756764),t=!!t,r=r||[],r.push({formElementIdentifierPath:e.get("__identifierPath"),validationResults:this.validateFormElement(e)}),t&&this.validationResultsHasErrors(r))return r;const i=e.get("renderables");if(Array.isArray(i)){for(let n=0,o=i.length;no===null||typeof o!="object"))c.on(t,"core/formElement/somePropertyChanged"),c.set(t,e,r);else for(const o of Object.keys(i)){const s=t===""?o:t+"."+o;c.on(s,"core/formElement/somePropertyChanged"),i[o]!==null&&(typeof i[o]=="object"||Array.isArray(i[o]))?S(c,i[o],s,r):c.set(s,i[o],r)}}}class N{constructor(){this.objectData={},this.publisherTopics={}}get(e){let t,r;for(a(l.isNonEmptyString(e),'Invalid parameter "key"',1475361755),r=this.objectData;e.indexOf(".")>0;){if(t=e.slice(0,e.indexOf(".")),e=e.slice(t.length+1),!(t in r))return;r=r[t]}return r[e]}set(e,t,r){let i,n,o,s,d;a(l.isNonEmptyString(e),'Invalid parameter "key"',1475361756),r=!!r;const p=this.get(e);for(d=this.objectData,i=e;i.indexOf(".")>0;)n=i.slice(0,i.indexOf(".")),i=i.slice(n.length+1),isNaN(Number(n))||(n=parseInt(n,10)),s=i.indexOf("."),o=s===-1?i:i.slice(0,s),typeof d[n]>"u"?isNaN(Number(o))?d[n]={}:d[n]=[]:isNaN(Number(o))&&Array.isArray(d[n])&&(d[n]={...d[n]}),d=d[n];if(d[i]=t,!l.isUndefinedOrNull(this.publisherTopics[e])&&!r)for(let y=0,g=this.publisherTopics[e].length;y0?(i=e.split("."),n=i.pop(),i=i.join("."),r=this.get(i),typeof r<"u"&&delete r[n]):a(!1,"remove toplevel properties is not supported",1489319753),!l.isUndefinedOrNull(this.publisherTopics[e])&&!t)for(let s=0,d=this.publisherTopics[e].length;st!==r))}getObjectData(){return R(this.objectData)}toString(){const e=this.getObjectData(),{renderables:t,__parentRenderable:r,...i}=e,n=t||null;let o=null;l.isUndefinedOrNull(r)||(o=r.getObjectData().__identifierPath+" (filtered)");const s=i;if(o!==null&&(s.__parentRenderable=o),n!==null&&Array.isArray(n)){const d=[];for(let p=0,y=n.length;p{a(typeof g=="object"&&g!==null&&!Array.isArray(g),'Invalid parameter "formElement"',1475364961),a(l.isNonEmptyString(I),'Invalid parameter "pathPrefix"',1475364962);const h=g.get("__identifierPath"),f=I+"/"+g.get("identifier"),v=u().getCurrentState("propertyValidationServiceRegisteredValidators");l.isUndefinedOrNull(v[h])||(v[f]=v[h],delete v[h]),u().setCurrentState("propertyValidationServiceRegisteredValidators",v),g.set("__identifierPath",f,i);const m=g.get("renderables");if(Array.isArray(m))for(let b=0,F=m.length;b{a(typeof r=="object"&&r!==null&&!Array.isArray(r),'Invalid parameter "formElement"',1475364961);const i=this.getFormEditorDefinition("formElements",r.get("type"));!i._isTopLevelFormElement&&!i._isCompositeFormElement&&e.push(r);const n=r.get("renderables");if(Array.isArray(n))for(let o=0,s=n.length;o{let n;if(i.get("identifier")===e&&(t=!0),!t&&(n=i.get("renderables"),Array.isArray(n)))for(let o=0,s=n.length;o0&&(F=p[f][m-1].identifier),C.addPropertyCollectionElement(L,f,h,F,!0),++m}}if(Array.isArray(s.editors))for(const f of s.editors)f.propertyPath&&h.on(f.propertyPath,"core/formElement/somePropertyChanged");if(i&&Array.isArray(s.editors))for(let f=0,v=s.editors.length;f{if(_.saveForm!==e)return;_.saveForm=null;const r=await t.resolve();r.status==="success"?A.publish("core/ajax/saveFormDefinition/success",[r]):A.publish("core/ajax/saveFormDefinition/error",[r])}).catch(async t=>{if(t instanceof P){const r=await t.resolve();A.publish("core/ajax/error",[t.response.statusText,r])}})}renderFormDefinitionPage(e){a(!isNaN(Number(e)),'Invalid parameter "pageIndex"',1475377781),a(l.isNonEmptyString(this.endpoints.formPageRenderer),'The endpoint "formPageRenderer" is not configured',1473447677),_.renderFormDefinitionPage&&_.renderFormDefinitionPage.abort();const t=new D(this.endpoints.formPageRenderer);_.renderFormDefinitionPage=t,t.post({formDefinition:JSON.stringify(l.convertToSimpleObject(u().getCurrentState("formDefinition"))),pageIndex:e,prototypeName:this.prototypeName,formPersistenceIdentifier:this.persistenceIdentifier}).then(async r=>{if(_.renderFormDefinitionPage!==t)return;_.renderFormDefinitionPage=null;const i=await r.resolve();A.publish("core/ajax/renderFormDefinitionPage/success",[i,e])}).catch(async r=>{if(r instanceof P){const i=await r.resolve();A.publish("core/ajax/error",[r.response.statusText,i])}})}}class x{constructor(){this.stackSize=10,this.stackPointer=0,this.stack=[]}add(e,t){a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "applicationState"',1477847415),t=!!t,Object.assign(e,{propertyValidationServiceRegisteredValidators:R(this.getCurrentState("propertyValidationServiceRegisteredValidators")??{})}),this.stack.splice(0,0,e),this.stack.length>this.stackSize&&this.stack.splice(this.stackSize-1,this.stack.length-this.stackSize),t||A.publish("core/applicationState/add",[e,this.getCurrentStackPointer(),this.getCurrentStackSize()])}addAndReset(e,t){a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "applicationState"',1477872641),this.stackPointer>0&&this.stack.splice(0,this.stackPointer),this.stackPointer=0,this.add(e,!0),t||A.publish("core/applicationState/add",[this.getCurrentState(),this.getCurrentStackPointer(),this.getCurrentStackSize()])}getCurrentState(e){if(e===void 0)return this.stack[this.stackPointer]||void 0;if(a(e==="formDefinition"||e==="currentlySelectedPageIndex"||e==="currentlySelectedFormElementIdentifierPath"||e==="propertyValidationServiceRegisteredValidators",'Invalid parameter "type"',1477932754),!(typeof this.stack[this.stackPointer]>"u"))return this.stack[this.stackPointer][e]}setCurrentState(e,t){a(e==="formDefinition"||e==="currentlySelectedPageIndex"||e==="currentlySelectedFormElementIdentifierPath"||e==="propertyValidationServiceRegisteredValidators",'Invalid parameter "type"',1477934111),this.stack[this.stackPointer][e]=t}setMaximalStackSize(e){a(typeof e=="number",'Invalid parameter "size"',1477846933),this.stackSize=e}getMaximalStackSize(){return this.stackSize}getCurrentStackSize(){return this.stack.length}getCurrentStackPointer(){return this.stackPointer}setCurrentStackPointer(e){a(typeof e=="number",'Invalid parameter "size"',1477852138),e<0?this.stackPointer=0:e>this.stack.length-1?this.stackPointer=this.stack.length-1:this.stackPointer=e}decrementCurrentStackPointer(){this.setCurrentStackPointer(--this.stackPointer)}incrementCurrentStackPointer(){this.setCurrentStackPointer(++this.stackPointer)}}function M(c){return a(l.isNonEmptyString(c),'Invalid parameter "ajaxRequestIdentifier"',1475358064),_[c]||null}const l=new O,W=new E,_={},j=new k,q=new x,A=new T,C=new w,J=new U;function H(){return l}function G(){return W}function K(){return j}function u(){return q}function Q(){return A}function X(){return J}function Y(){return C}export{x as ApplicationStateStack,E as DataBackend,U as Factory,N as Model,k as PropertyValidationService,T as PublisherSubscriber,w as Repository,O as Utility,a as assert,u as getApplicationStateStack,G as getDataBackend,X as getFactory,K as getPropertyValidationService,Q as getPublisherSubscriber,Y as getRepository,M as getRunningAjaxRequest,H as getUtility}; diff --git a/Resources/Public/JavaScript/backend/form-editor/helper.js b/Resources/Public/JavaScript/backend/form-editor/helper.js new file mode 100644 index 0000000..616961a --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/helper.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{merge as E}from"lodash-es";let d=null,r=null;const p={domElementClassNames:{active:"active",buttonCollectionElementRemove:"formeditor-inspector-collection-element-remove-button",buttonFormEditor:"formeditor-button",disabled:"disabled",hidden:"hidden",icon:"formeditor-icon",sortableHover:"sortable-hover"},domElementDataAttributeNames:{elementIdentifier:"data-element-identifier-path",identifier:"data-identifier",template:"data-template-name",templateProperty:"data-template-property"},domElementSelectorPattern:{bracesWithKey:"[{0}]",bracesWithKeyValue:'[{0}="{1}"]',class:".{0}",id:"#{0}",keyValue:'{0}="{1}"'}};function s(){return d}function l(){return s().getUtility()}function a(e,n,t){return s().assert(e,n,t)}function b(e){return a(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "partialConfiguration"',1478950623),r=E({},p,e),this}function c(e,n){let t;a(!l().isUndefinedOrNull(r.domElementSelectorPattern[e]),'Invalid parameter "patternIdentifier" ('+e+")",1478801251),a(Array.isArray(n),'Invalid parameter "replacements"',1478801252),t=r.domElementSelectorPattern[e];for(let m=0,f=n.length;mnull),ge={domElementClassNames:{buttonFormElementRemove:"formeditor-inspector-element-remove-button",collectionElement:"formeditor-inspector-collection-element",finisherEditorPrefix:"t3-form-inspector-finishers-editor-",inspectorEditor:"formeditor-inspector-element",inspectorInputGroup:"input-group",sortable:"sortable",validatorEditorPrefix:"formeditor-inspector-validators-editor-"},domElementDataAttributeNames:{contentElementSelectorTarget:"data-insert-target",finisher:"data-finisher-identifier",validator:"data-validator-identifier",randomId:"data-random-id",randomIdTarget:"data-random-id-attribute",randomIdIndex:"data-random-id-number",maximumFileSize:"data-maximumFileSize"},domElementDataAttributeValues:{collapse:"actions-view-table-expand",editorControlsInputGroup:"inspectorEditorControlsGroup",editorWrapper:"editorWrapper",editorControlsWrapper:"inspectorEditorControlsWrapper",formElementHeaderEditor:"inspectorFormElementHeaderEditor",formElementSelectorControlsWrapper:"inspectorEditorFormElementSelectorControlsWrapper",formElementSelectorSplitButtonContainer:"inspectorEditorFormElementSelectorSplitButtonContainer",formElementSelectorSplitButtonListContainer:"inspectorEditorFormElementSelectorSplitButtonListContainer",iconNotAvailable:"actions-close",inspector:"inspector","Inspector-CheckboxEditor":"Inspector-CheckboxEditor","Inspector-CollectionElementHeaderEditor":"Inspector-CollectionElementHeaderEditor","Inspector-FinishersEditor":"Inspector-FinishersEditor","Inspector-FormElementHeaderEditor":"Inspector-FormElementHeaderEditor","Inspector-PropertyGridEditor":"Inspector-PropertyGridEditor","Inspector-RemoveElementEditor":"Inspector-RemoveElementEditor","Inspector-RequiredValidatorEditor":"Inspector-RequiredValidatorEditor","Inspector-SingleSelectEditor":"Inspector-SingleSelectEditor","Inspector-MultiSelectEditor":"Inspector-MultiSelectEditor","Inspector-GridColumnViewPortConfigurationEditor":"Inspector-GridColumnViewPortConfigurationEditor","Inspector-TextareaEditor":"Inspector-TextareaEditor","Inspector-TextEditor":"Inspector-TextEditor","Inspector-Typo3WinBrowserEditor":"Inspector-Typo3WinBrowserEditor","Inspector-ValidatorsEditor":"Inspector-ValidatorsEditor","Inspector-ValidationErrorMessageEditor":"Inspector-ValidationErrorMessageEditor","Inspector-DateEditor":"Inspector-DateEditor",inspectorFinishers:"inspectorFinishers",inspectorValidators:"inspectorValidators",viewportButton:"viewportButton"},domElementIdNames:{finisherPrefix:"t3-form-inspector-finishers-",validatorPrefix:"t3-form-inspector-validators-"},isSortable:!0};let j=null,U=null;function v(){return U}function D(){return v().getViewModel()}function o(e){return d().isUndefinedOrNull(e)?M.setConfiguration(j):M.setConfiguration(e)}function d(){return v().getUtility()}function p(e,t,r){return v().assert(e,t,r)}function Ae(){return v().getRootFormElement()}function E(){return v().getCurrentlySelectedFormElement()}function w(){return v().getPublisherSubscriber()}function N(e,t){return v().getFormElementDefinition(e,t)}const Ie={ALLOWED_TAGS:["abbr","b","br","code","em","i","kbd","span","strong","u"],ALLOWED_ATTR:["class","title","role"]},Se={ALLOWED_TAGS:["a","abbr","blockquote","b","br","code","em","i","kbd","li","p","pre","span","strong","u","ul","ol"],ALLOWED_ATTR:["class","href","title","target","role","rel"]};function P(e,t){e&&(e.innerHTML=_.sanitize(t,Ie))}function q(e,t){e&&(e.innerHTML=_.sanitize(t,Se))}function G(e,t,r,l){switch(e.templateName){case"Inspector-FormElementHeaderEditor":J(e,t);break;case"Inspector-CollectionElementHeaderEditor":Q(e,t,r,l);break;case"Inspector-MaximumFileSizeEditor":X(e,t);break;case"Inspector-TextEditor":Z(e,t,r,l);break;case"Inspector-FinishersEditor":W("finishers",e,t);break;case"Inspector-ValidatorsEditor":W("validators",e,t);break;case"Inspector-ValidationErrorMessageEditor":C(e,t);break;case"Inspector-RemoveElementEditor":pe(e,t,r,l);break;case"Inspector-RequiredValidatorEditor":ae(e,t,r,l);break;case"Inspector-CheckboxEditor":se(e,t,r,l);break;case"Inspector-CountrySelectEditor":H(e,t,r,l);break;case"Inspector-CountrySingleSelectEditor":ee(e,t,r,l);break;case"Inspector-SingleSelectEditor":te(e,t,r,l);break;case"Inspector-MultiSelectEditor":re(e,t,r,l);break;case"Inspector-GridColumnViewPortConfigurationEditor":ne(e,t);break;case"Inspector-PropertyGridEditor":le(e,t,r,l);break;case"Inspector-TextareaEditor":oe(e,t,r,l);break;case"Inspector-Typo3WinBrowserEditor":ie(e,t,r,l);break;case"Inspector-DateEditor":ue(e,t,r,l);break;default:break}w().publish("view/inspector/editor/insert/perform",[e,t,r,l])}function Te(e,t,r){const l=new URLSearchParams({mode:e,fieldReference:t,allowedTypes:r});V.advanced({type:V.types.iframe,content:TYPO3.settings.FormEditor.typo3WinBrowserUrl+"&"+l.toString(),size:V.sizes.large})}let z=!1;function Oe(){z||(z=!0,window.addEventListener("message",function(e){if(!Ee.verifyOrigin(e.origin))throw"Denied message sent by "+e.origin;if(e.data.actionName==="typo3:elementBrowser:elementAdded"){if(typeof e.data.fieldName>"u")throw"fieldName not defined in message";if(typeof e.data.value>"u")throw"value not defined in message";const t=e.data.value.split("_"),r=document.querySelector(o().getDomElementDataAttribute("contentElementSelectorTarget","bracesWithKeyValue",[e.data.fieldName]));if(r){const l=t.pop()??"",n=Number(r.dataset.maxItems??1);if(n===1)r.value=l;else{const s=r.value.split(",").filter(c=>c!=="");l!==""&&!s.includes(l)&&s.length0){let m=a?.id??"";m||(m="validation-error-"+Math.random().toString(36).substring(2,9),a&&(a.id=m)),a&&(a.innerHTML=' '+n[0]+"",a.setAttribute("role","alert")),i&&(i.setAttribute("aria-invalid","true"),i.setAttribute("aria-describedby",m)),D().setElementValidationErrorClass(L(t),"hasError")}else a&&(a.innerHTML="",a.removeAttribute("role")),i&&(i.removeAttribute("aria-invalid"),i.removeAttribute("aria-describedby")),D().removeElementValidationErrorClass(L(t),"hasError");n=v().validateFormElement(E()),l=e.split("."),l=l[0]+"."+l[1],r=!1;for(let m=0,u=n.length;m0){r=!0;break}r?D().setElementValidationErrorClass(c):D().removeElementValidationErrorClass(c)}function Y(e,t){p(Array.isArray(e),'Invalid configuration "errorCodes"',1489932939),p(Array.isArray(t),'Invalid configuration "propertyData"',1489932940);for(let r=0,l=e.length;r0&&s.editors[0].identifier==="header"&&(l=document.createElement("div"),l.classList.add("panel-body"),r=document.createElement("div"),r.classList.add("panel-collapse","collapse"),r.id=R(e,t),r.appendChild(l));for(let i=0;i0&&r?l.append(y):c.append(y),$(y),G(s.editors[i],y,t,e)}(a===2&&s.editors[0].identifier==="header"&&s.editors[1].identifier==="removeButton"||a===1&&s.editors[0].identifier==="header")&&c.querySelector(o().getDomElementDataIdentifierSelector("collapse"))?.remove(),j.isSortable&&n&&Ne(n,e)}function W(e,t,r){let l,n,s;p(d().isNonEmptyString(e),'Invalid configuration "collectionName"',1478362968),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorConfiguration"',1475423098),p(typeof r=="object"&&r!==null&&!Array.isArray(r),'Invalid parameter "editorHtml"',1475423099),p(d().isNonEmptyString(t.label),'Invalid configuration "label"',1475423100),p(Array.isArray(t.selectOptions),'Invalid configuration "selectOptions"',1475423101),e==="finishers"?(n=x(),l=Ae().get(e)):(n=F(),l=E().get(e)),n?.replaceChildren();const c=o().getTemplatePropertyElement("label",r);P(c,t.label);const a=o().getTemplatePropertyElement("selectOptions",r),i=!d().isUndefinedOrNull(l)&&l.length>0;if(i)for(let m=0,u=l.length;ma.remove());const n=o().getTemplatePropertyElement("numbersOfColumnsToUse",t)?.cloneNode(!0);o().getTemplatePropertyElement("numbersOfColumnsToUse",t)?.remove();const s=L(t),c=function(a){o().getTemplatePropertyElement("numbersOfColumnsToUse",t)?.replaceChildren(),o().getTemplatePropertyElement("numbersOfColumnsToUse",t)?.remove();const i=n?.cloneNode(!0);K(t)?.after(i),i?.querySelector("input")?.focus();const m=o().getTemplatePropertyElement("numbersOfColumnsToUse-label",i);m&&P(m,e.configurationOptions.numbersOfColumnsToUse.label.replace("{@viewPortLabel}",a.dataset.viewPortLabel??""));const u=o().getTemplatePropertyElement("numbersOfColumnsToUse-description",i);u&&q(u,e.configurationOptions.numbersOfColumnsToUse.description);const y=e.configurationOptions.numbersOfColumnsToUse.propertyPath.replace("{@viewPortIdentifier}",a.dataset.viewPortIdentifier??""),b=o().getTemplatePropertyElement("numbersOfColumnsToUse-propertyPath",i);if(b){let f=function(){(this.value===""||isNaN(Number(this.value)))&&(this.value=""),E().set(y,this.value)};b.value=E().get(y)??"",b.addEventListener("keyup",f),b.addEventListener("paste",f),b.addEventListener("change",f)}};for(let a=0,i=e.configurationOptions.viewPorts.length;a{a.addEventListener("click",function(){s.querySelectorAll("button").forEach(i=>i.classList.remove(o().getDomElementClassName("active"))),this.classList.add(o().getDomElementClassName("active")),c(this)})})}function le(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1475419226),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1475419227),p(typeof e.enableAddRow=="boolean",'Invalid configuration "enableAddRow"',1475419228),p(typeof e.enableDeleteRow=="boolean",'Invalid configuration "enableDeleteRow"',1475419230),p(typeof e.isSortable=="boolean",'Invalid configuration "isSortable"',1475419229),p(d().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475419231),p(d().isNonEmptyString(e.label),'Invalid configuration "label"',1475419232),P(o().getTemplatePropertyElement("label",t),e.label),I(e,t);const n=(()=>{const y=v().buildPropertyPath(void 0,r,l,void 0,!0);return d().isNonEmptyString(y)?y+".":y})(),s=d().isUndefinedOrNull(e.multiSelection)?!1:!!e.multiSelection,c=d().isNonEmptyArray(e.gridColumns)?e.gridColumns.some(y=>y.name==="selected"):!0,a=(()=>{const y=E().get(n+"defaultValue");return d().isUndefinedOrNull(y)?{}:s?y:{0:y}})(),i=(()=>{const y=E(),b=n+e.propertyPath,f=y.get(b)||{};let A;return Array.isArray(f)?A=f.map((h,S)=>({id:"fe"+Math.floor(Math.random()*42)+Date.now(),label:d().isUndefinedOrNull(h._label)?h:h._label,value:d().isUndefinedOrNull(h._label)?S:h._value,selected:!1})):typeof f=="object"&&(A=Object.entries(f).map(([h,S])=>({id:"fe"+Math.floor(Math.random()*42)+Date.now(),label:S,value:h,selected:!1}))),A.map(h=>{for(const S of Object.keys(a))if(a[S]===h.value){h.selected=!0;break}return h})})(),m=d().isUndefinedOrNull(e.useLabelAsFallbackValue)?!0:e.useLabelAsFallbackValue,u=t.querySelector("typo3-form-property-grid-editor");u.enableAddRow=e.enableAddRow,u.enableSelection=c,u.enableMultiSelection=s,u.enableSorting=e.isSortable??!1,u.enableDeleteRow=e.enableDeleteRow??!1,u.enableLabelAsFallbackValue=m,u.entries=i,d().isNonEmptyArray(e.gridColumns)&&e.gridColumns.forEach(y=>{y.name==="label"&&(u.labelLabel=y.title,u.enableLabelFormElementSelectionButton=y.enableFormelementSelectionButton),y.name==="value"&&(u.labelValue=y.title,u.enableValueFormElementSelectionButton=y.enableFormelementSelectionButton),y.name==="selected"&&(u.labelSelected=y.title)}),(u.enableLabelFormElementSelectionButton||u.enableValueFormElementSelectionButton)&&(u.formElements=me()),u.addEventListener(fe.eventName,y=>{const b=y.data,f=[],A=[];for(const h of b){const S=h.label,O=h.value===""?h.label:d().canBeInterpretedAsInteger(h.value)?parseInt(h.value,10):h.value;h.selected&&f.push(O),A.push({_label:S,_value:O})}s?E().set(n+"defaultValue",f):E().set(n+"defaultValue",f[0]??"",!0),E().set(n+e.propertyPath,A),g(n+e.propertyPath,t)}),g(n+e.propertyPath,t)}function ae(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1475417093),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1475417094),p(d().isNonEmptyString(e.validatorIdentifier),'Invalid configuration "validatorIdentifier"',1475417095),p(d().isNonEmptyString(e.label),'Invalid configuration "label"',1475417096);const n=e.validatorIdentifier;P(o().getTemplatePropertyElement("label",t),e.label);let s,c,a;d().isNonEmptyString(e.propertyPath)&&(c=v().buildPropertyPath(e.propertyPath,r,l)),d().isNonEmptyString(e.propertyValue)?s=e.propertyValue:s="";const i=v().buildPropertyPath(e.configurationOptions.validationErrorMessage.propertyPath),m=o().getTemplatePropertyElement("validationErrorMessage",t),u=m?.cloneNode(!0);m?.remove();const y=function(){const f=u?.cloneNode(!0);K(t)?.after(f),P(o().getTemplatePropertyElement("validationErrorMessage-label",f),e.configurationOptions.validationErrorMessage.label),q(o().getTemplatePropertyElement("validationErrorMessage-description",f),e.configurationOptions.validationErrorMessage.description),a=E().get(i),d().isUndefinedOrNull(a)&&(a=[]);const A=Y(e.configurationOptions.validationErrorMessage.errorCodes,a),h=o().getTemplatePropertyElement("validationErrorMessage-propertyPath",f);!d().isUndefinedOrNull(A)&&h&&(h.value=A),h?.addEventListener("keyup",S),h?.addEventListener("paste",S);function S(){let O=E().get(i);d().isUndefinedOrNull(O)&&(O=[]),E().set(i,B(e.configurationOptions.validationErrorMessage.errorCodes,O,this.value))}},b=t.querySelector('input[type="checkbox"]');v().getIndexFromPropertyCollectionElement(n,"validators")!==-1&&(b&&(b.checked=!0),y()),b?.addEventListener("change",function(){o().getTemplatePropertyElement("validationErrorMessage",t)?.replaceChildren(),o().getTemplatePropertyElement("validationErrorMessage",t)?.remove(),this.checked?(y(),w().publish("view/inspector/collectionElement/new/selected",[n,"validators"]),d().isNonEmptyString(c)&&E().set(c,s)):(d().isNonEmptyString(c)&&E().unset(c),w().publish("view/inspector/removeCollectionElement/perform",[n,"validators"]),a=E().get(i),d().isUndefinedOrNull(a)&&(a=[]),E().set(i,B(e.configurationOptions.validationErrorMessage.errorCodes,a,"")))})}function se(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1476218671),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1476218672),p(d().isNonEmptyString(e.label),'Invalid configuration "label"',1476218673),p(d().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1476218674),P(o().getTemplatePropertyElement("label",t),e.label),I(e,t);const n=v().buildPropertyPath(e.propertyPath,r,l),s=E().get(n),c=e.propertyPath==="renderingOptions.enabled"&&d().isUndefinedOrNull(s),a=t.querySelector('input[type="checkbox"]');(c||typeof s=="boolean"&&s||s==="true"||s===1||s==="1")&&a&&(a.checked=!0),a?.addEventListener("change",function(){E().set(n,this.checked)})}function oe(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1475412567),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1475412568),p(d().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1475416098),p(d().isNonEmptyString(e.label),'Invalid configuration "label"',1475416099);const n=v().buildPropertyPath(e.propertyPath,r,l);P(o().getTemplatePropertyElement("label",t),e.label),I(e,t);const s=E().get(n),c=t.querySelector("textarea");if(!c)throw new Error("Textarea element not found in editor HTML");c.value=s;const a=e.rteOptions||{};if(e.enableRichtext===!0&&a&&typeof a=="object"&&Object.keys(a).length!==0){const u=c.parentElement;if(!u)throw new Error("Textarea wrapper element not found");if(Pe){const y=c.id,b=y?y+"ckeditor5":"",f=document.createElement("typo3-rte-ckeditor-ckeditor5");b&&(f.id=b);const A=JSON.stringify(a);f.setAttribute("options",A),c.setAttribute("slot","textarea"),f.appendChild(c),u.innerHTML="",u.appendChild(f),f.options=a}}g(n,t);const i=e.enableRichtext===!0?["change"]:["keyup","paste"],m=u=>{const y=u.target;E().set(n,y.value),g(n,t)};i.forEach(u=>{c.addEventListener(u,m)})}function ie(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1477300587),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1477300588),p(d().isNonEmptyString(e.label),'Invalid configuration "label"',1477300589),p(d().isNonEmptyString(e.buttonLabel),'Invalid configuration "buttonLabel"',1477318981),p(d().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1477300590),P(o().getTemplatePropertyElement("label",t),e.label),P(o().getTemplatePropertyElement("buttonLabel",t),e.buttonLabel),I(e,t);const n=t.querySelector("form");n&&(n.name=e.propertyPath),T.getIcon(e.iconIdentifier,T.sizes.small).then(function(m){const u=o().getTemplatePropertyElement("image",t);if(u){const y=document.createElement("div");y.innerHTML=m,u.append(y.firstElementChild??y)}}),o().getTemplatePropertyElement("onclick",t)?.addEventListener("click",function(){const m=Math.floor(Math.random()*1e5+1),u=this.closest(o().getDomElementDataIdentifierSelector("editorControlsWrapper"))?.querySelector(o().getDomElementDataAttribute("contentElementSelectorTarget","bracesWithKey"));u&&u.setAttribute(o().getDomElementDataAttribute("contentElementSelectorTarget"),String(m)),Te("db",String(m),e.browsableType)}),Oe();const s=v().buildPropertyPath(e.propertyPath,r,l),c=E().get(s);g(s,t);const a=o().getTemplatePropertyElement("propertyPath",t);if(a){a.value=c??"";const m=d().isUndefinedOrNull(e.maxItems)?1:e.maxItems;a.dataset.maxItems=m.toString()}a?.addEventListener("keyup",i),a?.addEventListener("paste",i);function i(){E().set(s,this.value),g(s,t)}}function pe(e,t,r,l){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1475412563),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1475412564);const n=t.querySelector("button");d().isUndefinedOrNull(r)?n?.classList.add(o().getDomElementClassName("buttonFormElementRemove"),o().getDomElementClassName("buttonFormEditor")):n?.classList.add(o().getDomElementClassName("buttonCollectionElementRemove")),n?.addEventListener("click",function(){d().isUndefinedOrNull(r)?D().showRemoveFormElementModal():D().showRemoveCollectionElementModal(r,l)})}function ce(e,t,r){p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "editorConfiguration"',1484574704),p(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "editorHtml"',1484574705),p(d().isNonEmptyString(r),'Invalid parameter "propertyPath"',1484574706);const l=t.querySelector("typo3-form-element-selector");if(l)if(e.enableFormelementSelectionButton===!0)l.elements=me(),l.addEventListener(he.eventName,n=>{let s;s=E().get(r)||"",s.length===0?s=`{${n.value}}`:s=`${s} {${n.value}}`,E().set(r,s);const c=o().getTemplatePropertyElement("propertyPath",t);c&&(c.value=s),g(r,t)});else{l.remove();const n=t.querySelector('[data-identifier="inspectorEditorControlsGroup"]');n&&n.classList.remove("input-group")}}function me(){return v().getNonCompositeNonToplevelFormElements().map(t=>({icon:N(t,"iconIdentifier"),label:t.get("label"),value:t.get("identifier")}))}function de(e){d().isUndefinedOrNull(e)&&(e=E()),p(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1478967319);let t;e.get("type")==="Form"?t=e.get("type"):t=N(e,"label")?N(e,"label"):e.get("identifier");const r=document.createElement("span");return r.textContent=t,r}function ue(e,t,r,l){p(typeof e=="object"&&e!==null,'Invalid parameter "editorConfiguration"',1740000001),p(typeof t=="object"&&t!==null,'Invalid parameter "editorHtml"',1740000002),p(d().isNonEmptyString(e.propertyPath),'Invalid configuration "propertyPath"',1740000003);const n=v().buildPropertyPath(e.propertyPath,r,l);P(o().getTemplatePropertyElement("label",t),e.label||""),I(e,t);const s=t.querySelector("typo3-form-date-editor"),c=TYPO3.settings.FormEditor.dateEditor;p(d().isNonEmptyString(c.absolutePattern),"Missing required TYPO3.settings.FormEditor.dateEditor.absolutePattern",1740000004),s.setAttribute("absolute-pattern",c.absolutePattern),s.value=E().get(n)||"",g(n,t),s.addEventListener(ve.eventName,a=>{const i=a.value;if(E().set(n,i),!d().isUndefinedOrNull(e.additionalElementPropertyPaths)&&Array.isArray(e.additionalElementPropertyPaths))for(let m=0,u=e.additionalElementPropertyPaths.length;m{e().onViewReadyBatch()}),r().subscribe("core/applicationState/add",(i,[t,o,s])=>{e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderRedo"))),s>1&&o<=s?e().enableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderUndo"))):e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderUndo")))}),r().subscribe("core/ajax/saveFormDefinition/success",(i,[t])=>{n().setUnsavedContent(!1),e().setPreviewMode(!1),e().showSaveSuccessMessage(),e().showSaveButtonSaveIcon(),n().setFormDefinition(t.formDefinition),e().addStructureRootElementSelection(),n().setCurrentlySelectedFormElement(a()),e().setStructureRootElementTitle(),e().setStageHeadline(),e().renderAbstractStageArea(),e().renewStructure(),e().renderPagination(),e().renderInspectorEditors()}),r().subscribe("core/ajax/saveFormDefinition/error",(i,[t])=>{e().showSaveButtonSaveIcon(),e().showSaveErrorMessage({message:t.message})}),r().subscribe("core/ajax/renderFormDefinitionPage/success",(i,[t,o])=>{e().renderPreviewStageArea(t)}),r().subscribe("core/ajax/error",(i,[t,o])=>{e().showErrorFlashMessage(t,o),e().renderPreviewStageArea(o)}),r().subscribe("view/header/button/save/clicked",()=>{n().validationResultsHasErrors(n().validateFormElementRecursive(a(),!0))?e().showValidationErrorsModal():(e().showSaveButtonSpinnerIcon(),n().saveFormDefinition())}),r().subscribe("view/header/formSettings/clicked",()=>{e().setPreviewMode(!1),e().addStructureRootElementSelection(),n().setCurrentlySelectedFormElement(a()),e().renderAbstractStageArea(),e().renewStructure(),e().renderPagination(),e().showInspectorSidebar(),e().renderInspectorEditors()}),r().subscribe("view/header/button/newPage/clicked",(i,[t])=>{n().isRootFormElementSelected()&&e().selectPageBatch(0),e().showInsertPagesModal(t)}),r().subscribe("view/header/button/close/clicked",()=>{e().showCloseConfirmationModal()}),r().subscribe("view/undoButton/clicked",()=>{e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderUndo"))),e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderRedo"))),n().undoApplicationState(),e().getPreviewMode()?n().renderCurrentFormPage():e().renderAbstractStageArea(),n().setUnsavedContent(!0),e().renewStructure(),e().renderPagination(),e().renderInspectorEditors()}),r().subscribe("view/redoButton/clicked",()=>{e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderUndo"))),e().disableButton(document.querySelector(d().getDomElementDataIdentifierSelector("buttonHeaderRedo"))),n().redoApplicationState(),e().getPreviewMode()?n().renderCurrentFormPage():e().renderAbstractStageArea(),n().setUnsavedContent(!0),e().renewStructure(),e().renderPagination(),e().renderInspectorEditors()}),r().subscribe("view/stage/element/clicked",(i,[t])=>{e().getPreviewMode()||l().get("__identifierPath")!==t&&(n().setCurrentlySelectedFormElement(t),e().selectStructureNode(),e().renewStructure(),e().refreshSelectedElementItemsBatch(),e().addAbstractViewValidationResults(),e().showInspectorSidebar(),e().renderInspectorEditors(),e().focusFirstInspectorInput())}),r().subscribe("view/stage/abstract/elementToolbar/button/newElement/clicked",(i,[t,o])=>{n().isRootFormElementSelected()&&e().selectPageBatch(0),e().showInsertElementsModal(t,o)}),r().subscribe("view/stage/abstract/button/newElement/clicked",(i,[t,o])=>{n().isRootFormElementSelected()&&e().selectPageBatch(0),e().showInsertElementsModal(t,o||void 0)}),r().subscribe("view/stage/abstract/dnd/start",(i,[t,o])=>{e().onAbstractViewDndStartBatch(t,o)}),r().subscribe("view/stage/abstract/dnd/stop",(i,[t])=>{n().setCurrentlySelectedFormElement(t),e().renewStructure(),e().setPreviewMode(!1),e().renderAbstractStageArea(),e().refreshSelectedElementItemsBatch(),e().addAbstractViewValidationResults(),e().renderInspectorEditors()}),r().subscribe("view/stage/abstract/dnd/change",(i,[t,o,s])=>{e().onAbstractViewDndChangeBatch(t,o,s)}),r().subscribe("view/stage/abstract/dnd/update",(i,[t,o,s,c])=>{e().onAbstractViewDndUpdateBatch(t,o,s,c)}),r().subscribe("view/viewModeButton/abstract/clicked",()=>{e().getPreviewMode()&&(e().setPreviewMode(!1),e().renderAbstractStageArea())}),r().subscribe("view/viewModeButton/preview/clicked",()=>{e().getPreviewMode()||(e().setPreviewMode(!0),n().renderCurrentFormPage())}),r().subscribe("view/paginationPrevious/clicked",()=>{e().selectPageBatch(n().getCurrentlySelectedPageIndex()-1),e().getPreviewMode()?n().renderCurrentFormPage():e().renderAbstractStageArea()}),r().subscribe("view/paginationNext/clicked",()=>{e().selectPageBatch(n().getCurrentlySelectedPageIndex()+1),e().getPreviewMode()?n().renderCurrentFormPage():e().renderAbstractStageArea()}),r().subscribe("view/stage/abstract/render/postProcess",()=>{e().renderUndoRedo(),e().addAbstractViewValidationResults()}),r().subscribe("view/stage/preview/render/postProcess",()=>{e().renderUndoRedo()}),r().subscribe("view/tree/node/clicked",(i,[t])=>{l().get("__identifierPath")!==t&&(n().setCurrentlySelectedFormElement(t),e().setPreviewMode(!1),e().renderAbstractStageArea(),e().renderPagination(),e().addAbstractViewValidationResults(),e().showInspectorSidebar(),e().renderInspectorEditors(),e().focusFirstInspectorInput())}),r().subscribe("view/tree/node/changed",(i,[t,o])=>{const s=n().getFormElementByIdentifierPath(t);s.set("label",o),e().getStructure().setTreeNodeTitle(null,s),l().get("__identifierPath")===t&&e().renderInspectorEditors(t)}),r().subscribe("view/structure/root/selected",()=>{n().isRootFormElementSelected()||(e().addStructureRootElementSelection(),n().setCurrentlySelectedFormElement(a()),e().setPreviewMode(!1),e().renderAbstractStageArea(),e().renewStructure(),e().renderPagination(),e().renderInspectorEditors())}),r().subscribe("view/structure/button/newPage/clicked",(i,[t])=>{n().isRootFormElementSelected()&&e().selectPageBatch(0),e().showInsertPagesModal(t)}),r().subscribe("view/tree/dnd/stop",(i,[t])=>{n().setCurrentlySelectedFormElement(t),e().renewStructure(),e().renderPagination(),e().setPreviewMode(!1),e().renderAbstractStageArea(),e().addAbstractViewValidationResults(),e().renderInspectorEditors()}),r().subscribe("view/tree/dnd/change",(i,[t,o,s])=>{e().onStructureDndChangeBatch(t,o,s)}),r().subscribe("view/tree/dnd/update",(i,[t,o,s,c])=>{e().onStructureDndUpdateBatch(t,o,s,c)}),r().subscribe("view/structure/renew/postProcess",()=>{e().addStructureValidationResults()}),r().subscribe("view/inspector/removeCollectionElement/perform",(i,[t,o,s])=>{e().removePropertyCollectionElement(t,o,s||void 0)}),r().subscribe("view/inspector/collectionElement/new/selected",(i,[t,o])=>{e().createAndAddPropertyCollectionElement(t,o)}),r().subscribe("view/inspector/collectionElement/existing/selected",(i,[t,o])=>{e().renderInspectorCollectionElementEditors(o,t)}),r().subscribe("view/inspector/collectionElements/dnd/update",(i,[t,o,s,c])=>{s?e().movePropertyCollectionElement(t,"before",s,c):o?e().movePropertyCollectionElement(t,"after",o,c):w(!1,"Next element or previous element need to be set.",1477407673)}),r().subscribe("core/formElement/somePropertyChanged",(i,[t,o,s,c])=>{t!=="renderables"&&(!n().isRootFormElementSelected()&&t==="label"?e().getStructure().setTreeNodeTitle():(!n().getUtility().isUndefinedOrNull(c)&&a().get("__identifierPath")===c&&(e().setStructureRootElementTitle(),e().setStageHeadline()),e().renewStructure()),e().getPreviewMode()?n().renderCurrentFormPage():e().renderAbstractStageArea(),e().addStructureValidationResults()),n().setUnsavedContent(!0)}),r().subscribe("view/formElement/removed",(i,[t])=>{n().setCurrentlySelectedFormElement(t),e().renewStructure(),e().renderAbstractStageArea(),e().renderPagination(),e().renderInspectorEditors()}),r().subscribe("view/formElement/inserted",(i,[t])=>{n().setCurrentlySelectedFormElement(t),e().renewStructure(),e().renderAbstractStageArea(),e().renderPagination(),e().renderInspectorEditors()}),r().subscribe("view/collectionElement/new/added",()=>{e().renderInspectorEditors()}),r().subscribe("view/collectionElement/moved",()=>{e().renderInspectorEditors()}),r().subscribe("view/collectionElement/removed",()=>{e().renderInspectorEditors()}),r().subscribe("view/insertElements/perform/bottom",(i,[t])=>{const o=n().getLastTopLevelElementOnCurrentPage();o?!n().getFormElementDefinition(o,"_isTopLevelFormElement")&&n().getFormElementDefinition(o,"_isCompositeFormElement")?e().createAndAddFormElement(t,n().getCurrentlySelectedPage()):e().createAndAddFormElement(t,o):e().createAndAddFormElement(t,n().getCurrentlySelectedPage())}),r().subscribe("view/insertElements/perform/before",(i,[t])=>{let o;o=e().createAndAddFormElement(t,void 0,!0),o=e().moveFormElement(o,"before",n().getCurrentlySelectedFormElement()),r().publish("view/formElement/inserted",[o])}),r().subscribe("view/insertElements/perform/after",(i,[t])=>{let o;o=e().createAndAddFormElement(t,void 0,!0),o=e().moveFormElement(o,"after",n().getCurrentlySelectedFormElement()),r().publish("view/formElement/inserted",[o])}),r().subscribe("view/insertElements/perform/inside",(i,[t])=>{e().createAndAddFormElement(t)}),r().subscribe("view/insertPages/perform",(i,[t])=>{e().createAndAddFormElement(t)}),r().subscribe("view/modal/close/perform",()=>{n().setUnsavedContent(!1),e().closeEditor()}),r().subscribe("view/modal/removeFormElement/perform",(i,[t])=>{e().removeFormElement(t)}),r().subscribe("view/modal/removeCollectionElement/perform",(i,[t,o,s])=>{e().removePropertyCollectionElement(t,o,s)}),r().subscribe("view/modal/validationErrors/element/clicked",(i,[t])=>{l().get("__identifierPath")!==t&&(n().setCurrentlySelectedFormElement(t),e().getPreviewMode()&&e().setPreviewMode(!1),e().renderAbstractStageArea(),e().renderPagination(),e().renderInspectorEditors())})}function p(i,t){m=i,b=t,u.bootstrap(m),v()}export{p as bootstrap}; diff --git a/Resources/Public/JavaScript/backend/form-editor/modals-component.js b/Resources/Public/JavaScript/backend/form-editor/modals-component.js new file mode 100644 index 0000000..afe1a44 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/modals-component.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import*as y from"@typo3/form/backend/form-editor/helper.js";import{merge as A}from"lodash-es";import d from"@typo3/backend/modal.js";import h from"@typo3/backend/severity.js";let w=null;const M={domElementClassNames:{buttonDefault:"btn-default",buttonInfo:"btn-info",buttonWarning:"btn-warning"},domElementDataAttributeNames:{elementType:"element-type",fullElementType:"data-element-type"},domElementDataAttributeValues:{rowItem:"rowItem",rowLink:"rowLink",rowsContainer:"rowsContainer",templateInsertElements:"Modal-InsertElements",templateInsertPages:"Modal-InsertPages",templateValidationErrors:"Modal-ValidationErrors"}};let D=null;function f(){return D}function r(e){return p().isUndefinedOrNull(e)?y.setConfiguration(w):y.setConfiguration(e)}function p(){return f().getUtility()}function u(e,t,n){return f().assert(e,t,n)}function i(){return f().getRootFormElement()}function b(){return f().getPublisherSubscriber()}function m(e,t){return f().getFormElementDefinition(e,t)}function I(e,t){const n=[];u(p().isNonEmptyString(e),'Invalid parameter "publisherTopicName"',1478889049),u(Array.isArray(t),'Invalid parameter "formElement"',1478889044),n.push({text:m(i(),"modalRemoveElementCancelButton"),active:!0,btnClass:r().getDomElementClassName("buttonDefault"),name:"cancel",trigger:(o,l)=>{l.hideModal()}}),n.push({text:m(i(),"modalRemoveElementConfirmButton"),active:!0,btnClass:r().getDomElementClassName("buttonWarning"),name:"confirm",trigger:(o,l)=>{b().publish(e,t),l.hideModal()}}),d.show(m(i(),"modalRemoveElementDialogTitle"),m(i(),"modalRemoveElementDialogMessage"),h.warning,n)}function C(e,t,n){if(u(p().isNonEmptyString(t),'Invalid parameter "publisherTopicName"',1478910954),typeof n=="object"&&n!==null&&!Array.isArray(n))for(const o of Object.keys(n)){if(o==="disableElementTypes"&&Array.isArray(n[o]))for(let l=0,E=n[o].length;la.classList.add(r().getDomElementClassName("disabled")));o==="onlyEnableElementTypes"&&Array.isArray(n[o])&&e.querySelectorAll(r().getDomElementDataAttribute("fullElementType","bracesWithKey")).forEach(l=>{const E=l.getAttribute(r().getDomElementDataAttribute("elementType"));n[o].some(c=>c===E)||l.classList.add(r().getDomElementClassName("disabled"))})}[...e.children].forEach(o=>o.addEventListener("typo3:form:insert-element-click",function(l){b().publish(t,[l.detail.item.identifier])}))}function S(e,t){let n,o;u(Array.isArray(t),'Invalid parameter "validationResults"',1479161268);const l=r().getDomElementDataIdentifierSelector("rowItem"),E=e.querySelector(l)?.cloneNode(!0);e.querySelectorAll(l).forEach(a=>a.remove());for(let a=0,c=t.length;a0){v=!0;break}if(v){n=f().getFormElementByIdentifierPath(t[a].formElementIdentifierPath),o=E?.cloneNode(!0);const s=o?.querySelector(r().getDomElementDataIdentifierSelector("rowLink"));s&&(s.setAttribute(r().getDomElementDataAttribute("elementIdentifier"),t[a].formElementIdentifierPath),s.replaceChildren(N(n)));const g=e.querySelector(r().getDomElementDataIdentifierSelector("rowsContainer"));g&&o&&g.append(o)}}e.querySelectorAll("a").forEach(a=>{a.addEventListener("click",function(){b().publish("view/modal/validationErrors/element/clicked",[a.getAttribute(r().getDomElementDataAttribute("elementIdentifier"))]),e.querySelectorAll("a").forEach(c=>c.replaceWith(c.cloneNode(!0))),d.currentModal.hideModal()})})}function N(e){u(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1479162557);const t=document.createElement("span");return t.textContent=e.get("label")?e.get("label"):e.get("identifier"),t}function T(e){I("view/modal/removeFormElement/perform",[e])}function B(e,t,n){u(p().isNonEmptyString(e),'Invalid parameter "collectionElementIdentifier"',1478894420),u(p().isNonEmptyString(t),'Invalid parameter "collectionName"',1478894421),I("view/modal/removeCollectionElement/perform",[e,t,n])}function P(){const e=[];e.push({text:m(i(),"modalCloseCancelButton"),active:!0,btnClass:r().getDomElementClassName("buttonDefault"),name:"cancel",trigger:(t,n)=>{n.hideModal()}}),e.push({text:m(i(),"modalCloseConfirmButton"),active:!0,btnClass:r().getDomElementClassName("buttonWarning"),name:"confirm",trigger:(t,n)=>{b().publish("view/modal/close/perform",[]),n.hideModal()}}),d.show(m(i(),"modalCloseDialogTitle"),m(i(),"modalCloseDialogMessage"),h.warning,e)}function R(e,t){const n=r().getTemplateElement("templateInsertElements");if(n){const o=document.importNode(n.content,!0);C(o,e,t),d.advanced({title:m(i(),"modalInsertElementsDialogTitle"),size:d.sizes.large,content:o})}}function k(e){const t=r().getTemplateElement("templateInsertPages");if(t){const n=document.importNode(t.content,!0);C(n,e),d.advanced({title:m(i(),"modalInsertPagesDialogTitle"),size:d.sizes.small,content:n})}}function F(e){const t=[];t.push({text:m(i(),"modalValidationErrorsConfirmButton"),active:!0,btnClass:r().getDomElementClassName("buttonDefault"),name:"confirm",trigger:function(o,l){l.hideModal()}});const n=r().getTemplateElement("templateValidationErrors");if(n){const o=document.importNode(n.content,!0);S(o,e),d.show(m(i(),"modalValidationErrorsDialogTitle"),o,h.error,t)}}function q(e,t){return D=e,w=A({},M,t??{}),y.bootstrap(D),this}export{q as bootstrap,P as showCloseConfirmationModal,R as showInsertElementsModal,k as showInsertPagesModal,B as showRemoveCollectionElementModal,T as showRemoveFormElementModal,F as showValidationErrorsModal}; diff --git a/Resources/Public/JavaScript/backend/form-editor/stage-component.js b/Resources/Public/JavaScript/backend/form-editor/stage-component.js new file mode 100644 index 0000000..70901dd --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/stage-component.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import*as L from"@typo3/form/backend/form-editor/helper.js";import{merge as G}from"lodash-es";import J from"sortablejs";import"@typo3/form/backend/form-editor/component/form-element-stage-item.js";import"@typo3/form/backend/form-editor/component/form-element-stage-item-toolbar.js";import"@typo3/form/backend/form-editor/component/page-stage-item.js";import Q from"~labels/form.form_editor_javascript";const X={domElementClassNames:{formElementIsComposit:"formeditor-element-composit",formElementIsTopLevel:"formeditor-element-toplevel",noNesting:"no-nesting",selected:"selected",sortable:"sortable",previewViewPreviewElement:"formeditor-element-preview"},domElementDataAttributeNames:{abstractType:"data-element-abstract-type",noSorting:"data-no-sorting"},domElementDataAttributeValues:{abstractViewToolbarNewElement:"stageElementToolbarNewElement",abstractViewToolbarNewElementSplitButton:"stageElementToolbarNewElementSplitButton",abstractViewToolbarNewElementSplitButtonAfter:"stageElementToolbarNewElementSplitButtonAfter",abstractViewToolbarNewElementSplitButtonInside:"stageElementToolbarNewElementSplitButtonInside",abstractViewToolbarRemoveElement:"stageElementToolbarRemoveElement",buttonHeaderRedo:"redoButton",buttonHeaderUndo:"undoButton",buttonPaginationPrevious:"buttonPaginationPrevious",buttonPaginationNext:"buttonPaginationNext",formElementIcon:"elementIcon",iconValidator:"form-validator",multiValueContainer:"multiValueContainer",paginationTitle:"paginationTitle",stageHeadline:"formDefinitionLabel",stagePanel:"stagePanel",validatorsContainer:"validatorsContainer",validatorIcon:"validatorIcon"},isSortable:!0};let N=null,F=null,d=null;function s(){return F}function l(e){return b().isUndefinedOrNull(e)?L.setConfiguration(N):L.setConfiguration(e)}function b(){return s().getUtility()}function v(){return s().getViewModel()}function w(e,t,n){return s().assert(e,t,n)}function T(){return s().getRootFormElement()}function O(){return s().getCurrentlySelectedFormElement()}function p(){return s().getPublisherSubscriber()}function c(e,t){return s().getFormElementDefinition(e,t)}function Y(e,t){p().publish("view/stage/abstract/render/template/perform",[e,t])}function Z(e,t){const n=document.createElement("li");n.setAttribute("data-no-sorting","true"),n.classList.add("formeditor-new-element-placeholder");const o=Q.get("formEditor.stage.toolbar.new_element"),i=document.createElement("button");i.type="button",i.title=o,i.classList.add("btn","btn-sm","btn-default");const r=document.createElement("typo3-backend-icon");return r.setAttribute("identifier","actions-plus"),r.setAttribute("size","small"),i.append(r,document.createTextNode(" "+o)),i.addEventListener("click",function(u){u.stopPropagation(),s().setCurrentlySelectedFormElement(e),t==="inside"?p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/inside",{disableElementTypes:[],onlyEnableElementTypes:[]}]):p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/after",{disableElementTypes:[],onlyEnableElementTypes:[]}])}),n.append(i),n}function U(e){let t;const n=document.createElement("li");c(e,"_isCompositeFormElement")||n.classList.add(l().getDomElementClassName("noNesting")),c(e,"_isTopLevelFormElement")&&n.classList.add(l().getDomElementClassName("formElementIsTopLevel")),c(e,"_isCompositeFormElement")&&n.classList.add(l().getDomElementClassName("formElementIsComposit"));let o;try{o=l().getTemplateElement("FormElement-"+e.get("type"))}catch{o=null}const i=o===null,r=document.createElement("div");r.setAttribute(l().getDomElementDataAttribute("elementIdentifier"),e.get("__identifierPath")),o&&r.append(document.importNode(o.content,!0));const u=c(e,"_isCompositeFormElement");u&&r.setAttribute(l().getDomElementDataAttribute("abstractType"),"isCompositeFormElement");const E=c(e,"_isTopLevelFormElement");if(E?r.setAttribute(l().getDomElementDataAttribute("abstractType"),"isTopLevelFormElement"):(r.classList.add("formeditor-element"),r.setAttribute("tabindex","0"),r.setAttribute("role","button"),r.setAttribute("aria-label",(e.get("label")||e.get("identifier"))+" ("+c(e,"label")+")")),e.get("renderingOptions.enabled")===!1&&r.classList.add("formeditor-element-hidden"),!E&&!i&&!r.querySelector("typo3-form-form-element-stage-item-toolbar")){const f=document.createElement("typo3-form-form-element-stage-item-toolbar");f.iconIdentifier=c(e,"iconIdentifier")||"",f.elementType=c(e,"label")||"",f.elementIdentifier=e.get("identifier")||"",f.isHidden=e.get("renderingOptions.enabled")===!1,f.active=!0,r.prepend(f)}if(n.append(r),E&&i?j(e,r):i?M(e,r):Y(e,r),E||u){t=document.createElement("ol"),t.classList.add(l().getDomElementClassName("sortable")),t.classList.add("formeditor-list");const f=e.get("renderables"),g=Array.isArray(f)&&f.length>0;if(g||t.append(Z(e,"inside")),g)for(let A=0,k=f.length;Adocument.querySelector(l().getDomElementDataIdentifierSelector(i));v().enableButton(t("buttonPaginationPrevious")),v().enableButton(t("buttonPaginationNext")),s().getCurrentlySelectedPageIndex()===0&&v().disableButton(t("buttonPaginationPrevious")),(e===1||s().getCurrentlySelectedPageIndex()===e-1)&&v().disableButton(t("buttonPaginationNext"));const n=s().getCurrentlySelectedPageIndex()+1,o=t("paginationTitle");o&&(o.textContent=c(T(),"paginationTitle").replace("{0}",n.toString()).replace("{1}",e))}function re(){const e=t=>document.querySelector(l().getDomElementDataIdentifierSelector(t));v().enableButton(e("buttonHeaderUndo")),v().enableButton(e("buttonHeaderRedo")),s().getCurrentApplicationStatePosition()+1>=s().getCurrentApplicationStates()&&v().disableButton(e("buttonHeaderUndo")),s().getCurrentApplicationStatePosition()===0&&v().disableButton(e("buttonHeaderRedo"))}function W(){return d?d.querySelectorAll(l().getDomElementDataAttribute("elementIdentifier","bracesWithKey")):document.querySelectorAll(".formeditor-element-none")}function _(e){w(typeof e=="number",'Invalid parameter "pageIndex"',1478721208);const t=document.createElement("ol");return t.classList.add("formeditor-stage-list"),t.append(U(T().get("renderables")[e])),t}function H(e){return e.parentElement?.closest("li")?.querySelector(l().getDomElementDataAttribute("elementIdentifier","bracesWithKey"))??null}function R(e){return H(e)?.getAttribute(l().getDomElementDataAttribute("elementIdentifier"))??""}function K(e){return e.querySelector(l().getDomElementDataAttribute("elementIdentifier","bracesWithKey"))}function P(e){return K(e)?.getAttribute(l().getDomElementDataAttribute("elementIdentifier"))??""}function V(e,t){b().isUndefinedOrNull(t)&&(t="prev");const n=P(e),o=t==="prev"?e.previousElementSibling:e.nextElementSibling;if(!o)return"";const i=l().getDomElementDataAttribute("elementIdentifier");return o.querySelector(l().getDomElementDataAttribute("elementIdentifier","bracesWithKey")+":not("+l().getDomElementDataAttribute("elementIdentifier","bracesWithKeyValue",[n])+")")?.getAttribute(i)??""}function oe(e){let t;return typeof e=="string"?t=e:b().isUndefinedOrNull(e)?t=O().get("__identifierPath"):t=e.get("__identifierPath"),d?d.querySelector(l().getDomElementDataAttribute("elementIdentifier","bracesWithKeyValue",[t])):null}function le(e,t){if(b().isUndefinedOrNull(t)&&(t=O()),e.querySelector("typo3-form-form-element-stage-item")||c(t,void 0)._isTopLevelFormElement)return;let i=e.querySelector("typo3-form-form-element-stage-item-toolbar");if(!i){const r=document.createElement("typo3-form-form-element-stage-item-toolbar");e.prepend(r),i=r}i.dataset.eventsWired||(i.dataset.eventsWired="true",i.addEventListener("toolbar-new-element-before",()=>{p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/before",{disableElementTypes:[]}])}),i.addEventListener("toolbar-new-element-after",()=>{p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/after",{disableElementTypes:[]}])}),i.addEventListener("toolbar-remove-element",()=>{v().showRemoveFormElementModal(t)})),i.active=!0}function ae(e,t){b().isUndefinedOrNull(e)&&(e=s().getCurrentlySelectedPageIndex()),d.replaceChildren(_(e)),d.addEventListener("click",function(n){const o=n.target.closest(l().getDomElementDataAttribute("elementIdentifier","bracesWithKey"))?.getAttribute(l().getDomElementDataAttribute("elementIdentifier"));b().isUndefinedOrNull(o)||!b().isNonEmptyString(o)||p().publish("view/stage/element/clicked",[o])}),d.addEventListener("keydown",function(n){const o=n.target.closest(".formeditor-element[tabindex]");o&&(n.key==="Enter"||n.key===" ")&&(n.preventDefault(),o.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0})))}),N.isSortable&&$(),typeof t=="function"&&t()}function se(e){w(b().isNonEmptyString(e),'Invalid parameter "html"',1475424409),d.replaceChildren(),d.innerHTML=e,d.querySelectorAll("input, select, textarea, button").forEach(t=>{t.disabled=!0,["click","dblclick","select","focus","keydown","keypress","keyup","mousedown","mouseup"].forEach(n=>{t.addEventListener(n,o=>o.preventDefault())})}),d.querySelector("form")?.addEventListener("submit",t=>t.preventDefault()),W().forEach(function(t){const n=s().getFormElementByIdentifierPath(t.dataset.elementIdentifierPath);c(n,"_isTopLevelFormElement")||t.setAttribute("title","identifier: "+n.get("identifier")+" (type: "+n.get("type")+")"),c(n,"_isTopLevelFormElement")&&t.classList.add(l().getDomElementClassName("formElementIsTopLevel")),c(n,"_isCompositeFormElement")&&t.classList.add(l().getDomElementClassName("formElementIsComposit"))})}function j(e,t){w(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1768924251);const n=document.createElement("typo3-form-page-stage-item");n.pageTitle=e.get("label")||"",t.replaceChildren(n)}function M(e,t){w(typeof e=="object"&&e!==null&&!Array.isArray(e),'Invalid parameter "formElement"',1768924252);const n=document.createElement("typo3-form-form-element-stage-item");n.elementType=c(e,"label"),n.elementIdentifier=e.get("identifier"),n.elementLabel=e.get("label")||e.get("identifier"),n.elementIconIdentifier=c(e,"iconIdentifier"),n.isHidden=e.get("renderingOptions.enabled")===!1;const o=e.get("validators"),i=[];let r=!1;if(Array.isArray(o)&&o.length>0)for(let a=0,m=o.length;a0&&(n.allowedMimeTypes=D),n.isHidden&&n.classList.add("formeditor-element-hidden");const C=s().validateFormElement(e);let q=!1;for(let a=0,m=C.length;a0){q=!0;break}n.invalid=q,n.addEventListener("toolbar-new-element-before",()=>{p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/before",{disableElementTypes:[]}])}),n.addEventListener("toolbar-new-element-after",()=>{p().publish("view/stage/abstract/elementToolbar/button/newElement/clicked",["view/insertElements/perform/after",{disableElementTypes:[]}])}),n.addEventListener("toolbar-remove-element",()=>{v().showRemoveFormElementModal(e)}),t.replaceChildren(n)}function de(e,t,n){return F=e,w(typeof t=="object"&&t!==null&&!Array.isArray(t),'Invalid parameter "appendToDomElement"',1478992119),d=t,N=G({},X,n??{}),L.bootstrap(F),this}export{de as bootstrap,B as buildTitleByFormElement,le as createAndAddAbstractViewFormElementToolbar,oe as getAbstractViewFormElementDomElement,P as getAbstractViewFormElementIdentifierPathWithinDomElement,K as getAbstractViewFormElementWithinDomElement,R as getAbstractViewParentFormElementIdentifierPathWithinDomElement,H as getAbstractViewParentFormElementWithinDomElement,V as getAbstractViewSiblingFormElementIdentifierPathWithinDomElement,W as getAllFormElementDomElements,ee as getStageDomElement,ne as getStagePanelDomElement,ae as renderAbstractStageArea,_ as renderFormDefinitionPageAsSortableList,M as renderFormElementStageItem,ie as renderPagination,se as renderPreviewStageArea,j as renderTopLevelStageItem,re as renderUndoRedo,te as setStageHeadline}; diff --git a/Resources/Public/JavaScript/backend/form-editor/tree-component-adapter.js b/Resources/Public/JavaScript/backend/form-editor/tree-component-adapter.js new file mode 100644 index 0000000..863482d --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/tree-component-adapter.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import*as B from"@typo3/form/backend/form-editor/helper.js";import{FORM_EDITOR_TREE_EVENTS as p}from"@typo3/form/backend/form-editor-tree-events.js";import{stripTags as G}from"@typo3/form/backend/form-editor/utility/string-utility.js";import"@typo3/form/backend/form-editor-tree-container.js";let b=null,i=null,o=null;function a(){return b}function d(){return a().getPublisherSubscriber()}function y(){return a().getRootFormElement()}function h(){return a().getCurrentlySelectedFormElement()}function u(e,t){return a().getFormElementDefinition(e,t)}function w(e){const t=e.get("label")||e.get("identifier"),n={identifier:e.get("identifier"),identifierPath:e.get("__identifierPath"),label:G(t),type:u(e,"label"),iconIdentifier:u(e,"iconIdentifier"),isComposite:u(e,"_isCompositeFormElement"),isTopLevel:u(e,"_isTopLevelFormElement"),enabled:e.get("renderingOptions.enabled")!==!1,children:[]},r=e.get("renderables");return Array.isArray(r)&&r.length>0&&(n.children=r.map(l=>w(l))),n}function K(){const e=y(),t=w(e);return t.expanded=!0,[t]}function E(e){if(!i)return;const t=K();requestAnimationFrame(async()=>{await i.setNodes(t);let n=e;if(!n)try{n=h()}catch{n=null}if(n){const r=n.get("__identifierPath");i.setSelectedNode(r)}d().publish("view/structure/renew/postProcess")})}function N(e){if(!i)return;let t=e;if(!t)try{t=h()}catch{return}i.setSelectedNode(t.get("__identifierPath"))}function F(e,t){if(!t)try{t=h()}catch{return}e&&t.set("label",e),E(t)}function D(e){let t;if(typeof e=="string")t=e;else{let n=e;if(!n)try{n=h()}catch{return null}t=n.get("__identifierPath")}return o?o.querySelector(`[data-id="${t}"]`):null}function S(){return o?o.querySelectorAll(".tree-item"):document.querySelectorAll(".tree-item-none")}function I(e,t=!0){i&&i.setNodeValidationError(e,t)}function A(e,t=!0){i&&i.setNodeChildHasError(e,t)}function C(){i&&i.clearAllValidationErrors()}function _(){return o}function L(e){const t=document.createElement("span");t.textContent=e.get("label")?e.get("label"):e.get("identifier");const n=document.createElement("small");return n.textContent="("+u(e,"label")+")",t.appendChild(n),t}function q(e){return e?e.querySelector(".tree-item-content"):null}function x(e){return e?.closest("[data-id]")?.getAttribute("data-id")??""}function O(e){const t=e?.parentElement?.closest("li[data-id]");return t?t.querySelector(".tree-item-content"):null}function R(e){return e?.parentElement?.closest("li[data-id]")?.getAttribute("data-id")??""}function W(e,t="prev"){const n=e?.closest("li[data-id]");return n?(t==="prev"?n.previousElementSibling?.matches("li[data-id]")?n.previousElementSibling:null:n.nextElementSibling?.matches("li[data-id]")?n.nextElementSibling:null)?.getAttribute("data-id")??"":""}function V(){return document.createElement("div")}function v(){return window.parent.document.querySelector("typo3-backend-navigation-component-formeditortree")}function M(){const e=v();return e?Promise.resolve(e):new Promise(t=>{const n=()=>{clearTimeout(r),window.parent.document.removeEventListener("typo3:tree-container:ready",n);const l=v();t(l)};window.parent.document.addEventListener("typo3:tree-container:ready",n);const r=window.setTimeout(()=>{window.parent.document.removeEventListener("typo3:tree-container:ready",n),console.warn("[FormEditor Tree Adapter] Tree container not found within timeout"),t(null)},5e3)})}function H(e,t){return b=e,o=t,i=v(),i?k():M().then(n=>{n&&(i=n,k(),b&&y()&&E())}),{renew:E,selectTreeNode:N,setTreeNodeTitle:F,getTreeNode:D,getAllTreeNodes:S,setNodeValidationError:I,setNodeChildHasError:A,clearAllValidationErrors:C,getTreeDomElement:_,buildTitleByFormElement:L,getTreeNodeWithinDomElement:q,getTreeNodeIdentifierPathWithinDomElement:x,getParentTreeNodeWithinDomElement:O,getParentTreeNodeIdentifierPathWithinDomElement:R,getSiblingTreeNodeIdentifierPathWithinDomElement:W,renderCompositeFormElementChildsAsSortableList:V,bootstrap:H}}function k(){i&&(i.addEventListener(p.NODE_CLICKED,e=>{const t=e,{identifierPath:n}=t.detail;try{d().publish("view/tree/node/clicked",[n])}catch{}}),i.addEventListener(p.NODE_EDIT,e=>{const t=e,{identifierPath:n}=t.detail;d().publish("view/tree/node/clicked",[n])}),i.addEventListener(p.DND_UPDATE,e=>{const t=e,{movedIdentifierPath:n,previousIdentifierPath:r,nextIdentifierPath:l}=t.detail,m=o?o.querySelector(`[data-id="${n}"]`):null;d().publish("view/tree/dnd/update",[m,n,r,l]),d().publish("view/tree/dnd/stop",[n])}),i.addEventListener(p.DND_CHANGE,e=>{const t=e,{itemIdentifierPath:n,parentIdentifierPath:r,position:l,previousIdentifierPath:m,nextIdentifierPath:P}=t.detail,g=o?o.querySelector(`[data-id="${n}"]`):null,$=a().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(r);d().publish("view/tree/dnd/change",[g,r,$]);let s,c;l==="inside"?(s="inside",c=r):P?(s="before",c=P):m?(s="after",c=m):(s="inside",c=r);try{const f=a().moveFormElement(n,s,c,!1),T=f.get("__identifierPath");f&&g!==null&&g.setAttribute(B.getDomElementDataAttribute("elementIdentifier"),T),d().publish("view/tree/dnd/stop",[T])}catch(f){console.error("[FormEditor Tree] Failed to move element:",f)}}))}export{H as bootstrap,L as buildTitleByFormElement,C as clearAllValidationErrors,S as getAllTreeNodes,R as getParentTreeNodeIdentifierPathWithinDomElement,O as getParentTreeNodeWithinDomElement,W as getSiblingTreeNodeIdentifierPathWithinDomElement,_ as getTreeDomElement,D as getTreeNode,x as getTreeNodeIdentifierPathWithinDomElement,q as getTreeNodeWithinDomElement,V as renderCompositeFormElementChildsAsSortableList,E as renew,N as selectTreeNode,A as setNodeChildHasError,I as setNodeValidationError,F as setTreeNodeTitle}; diff --git a/Resources/Public/JavaScript/backend/form-editor/utility/string-utility.js b/Resources/Public/JavaScript/backend/form-editor/utility/string-utility.js new file mode 100644 index 0000000..a9da742 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/utility/string-utility.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +function n(t){if(!t)return t;const e=document.createElement("div");return e.innerHTML=t,e.textContent||e.innerText||""}export{n as stripTags}; diff --git a/Resources/Public/JavaScript/backend/form-editor/view-model.js b/Resources/Public/JavaScript/backend/form-editor/view-model.js new file mode 100644 index 0000000..3187a87 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-editor/view-model.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{cloneDeep as de}from"lodash-es";import*as k from"@typo3/form/backend/form-editor/tree-component-adapter.js";import*as B from"@typo3/form/backend/form-editor/modals-component.js";import*as F from"@typo3/form/backend/form-editor/inspector-component.js";import*as me from"@typo3/form/backend/form-editor/stage-component.js";import*as N from"@typo3/form/backend/form-editor/helper.js";import y from"@typo3/backend/icons.js";import w from"@typo3/backend/notification.js";import{loadModule as ue}from"@typo3/core/java-script-item-processor.js";const O={domElementClassNames:{formElementIsComposit:"formeditor-element-composit",formElementIsTopLevel:"formeditor-element-toplevel",hasError:"has-error",selectedCompositFormElement:"selected",selectedFormElement:"selected",selectedRootFormElement:"selected",selectedStagePanel:"t3-form-form-stage-selected",sortableHover:"sortable-hover",viewModeAbstract:"formeditor-module-viewmode-abstract",viewModePreview:"formeditor-module-viewmode-preview"},domElementDataAttributeNames:{abstractType:"data-element-abstract-type"},domElementDataAttributeValues:{buttonHeaderClose:"closeButton",buttonHeaderPaginationNext:"buttonPaginationNext",buttonHeaderPaginationPrevious:"buttonPaginationPrevious",buttonHeaderRedo:"redoButton",buttonHeaderSave:"saveButton",buttonHeaderUndo:"undoButton",buttonHeaderViewModeAbstract:"buttonViewModeAbstract",buttonHeaderViewModePreview:"buttonViewModePreview",buttonFormSettings:"formSettings",buttonToggleStructure:"formeditorStructureToggle",buttonExpandInspector:"formeditorInspectorExpand",buttonCollapseInspector:"formeditorInspectorCollapse",buttonNewPage:"newPage",iconMailform:"content-form",iconSave:"actions-document-save",iconSaveSpinner:"spinner-circle",inspectorSection:"inspectorSection",moduleLoadingIndicator:"moduleLoadingIndicator",moduleWrapper:"moduleWrapper",stageArea:"stageArea",stageContainer:"stageContainer",stageContainerInner:"stageContainerInner",stagePanelHeading:"panelHeading",stageSection:"stageSection",structure:"structure-element",structureSection:"structureSection",structureRootContainer:"treeRootContainer",structureRootElement:"treeRootElement"}};let W=!1,I=null,_=null,j=null,z=null,K=null;function u(){return a().getRootFormElement()}function E(e,t,n){return a().assert(e,t,n)}function m(){return a().getUtility()}function v(){return a().getCurrentlySelectedFormElement()}function s(){return a().getPublisherSubscriber()}const ce=/^([0-9]{4})-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])$/i;function V(e){return ce.test(e)}function $(e){const t=e.trim();return t.length>0&&!V(t)}function fe(){a().addPropertyValidationValidator("NotEmpty",function(e,t){const n=e.get(t);if(!n||n===""||Array.isArray(n)&&!n.length)return a().getFormElementPropertyValidatorDefinition("NotEmpty").errorMessage||"invalid value"}),a().addPropertyValidationValidator("Integer",function(e,t){const n=e.get(t);if(n===""||n===null||isNaN(Number(n)))return a().getFormElementPropertyValidatorDefinition("Integer").errorMessage||"invalid value"}),a().addPropertyValidationValidator("IntegerOrEmpty",function(e,t){if(!m().isUndefinedOrNull(e.get(t))&&e.get(t).length>0&&isNaN(Number(e.get(t))))return a().getFormElementPropertyValidatorDefinition("Integer").errorMessage||"invalid value"}),a().addPropertyValidationValidator("NaiveEmail",function(e,t){if(!m().isUndefinedOrNull(e.get(t))&&!e.get(t).match(/\S+@\S+\.\S+/))return a().getFormElementPropertyValidatorDefinition("NaiveEmail").errorMessage||"invalid value"}),a().addPropertyValidationValidator("NaiveEmailOrEmpty",function(e,t){if(!m().isUndefinedOrNull(e.get(t))&&e.get(t).length>0&&!e.get(t).match(/\S+@\S+\.\S+/))return a().getFormElementPropertyValidatorDefinition("NaiveEmailOrEmpty").errorMessage||"invalid value"}),a().addPropertyValidationValidator("FormElementIdentifierWithinCurlyBracesInclusive",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const r=/\{([a-z0-9-_]+)?\}/gi.exec(e.get(t));if(r&&(r[1]&&r[1]!=="__currentTimestamp"&&!a().isFormElementIdentifierUsed(r[1])||!r[1]))return a().getFormElementPropertyValidatorDefinition("FormElementIdentifierWithinCurlyBracesInclusive").errorMessage||"invalid value"}),a().addPropertyValidationValidator("FormElementIdentifierWithinCurlyBracesExclusive",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const r=/^\{([a-z0-9-_]+)?\}$/i.exec(e.get(t));if(!r||r[1]&&r[1]!=="__currentTimestamp"&&!a().isFormElementIdentifierUsed(r[1])||!r[1])return a().getFormElementPropertyValidatorDefinition("FormElementIdentifierWithinCurlyBracesInclusive").errorMessage||"invalid value"}),a().addPropertyValidationValidator("FileSize",function(e,t){if(!m().isUndefinedOrNull(e.get(t))&&!e.get(t).match(/^(\d*\.?\d+)(B|K|M|G)$/i))return a().getFormElementPropertyValidatorDefinition("FileSize").errorMessage||"invalid value"}),a().addPropertyValidationValidator("RFC3339FullDate",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const n=e.get(t);if(!V(n)&&!$(n))return a().getFormElementPropertyValidatorDefinition("RFC3339FullDate").errorMessage||"invalid value"}),a().addPropertyValidationValidator("RFC3339FullDateOrEmpty",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const n=e.get(t);if(n.length>0&&!V(n)&&!$(n))return a().getFormElementPropertyValidatorDefinition("RFC3339FullDate").errorMessage||"invalid value"}),a().addPropertyValidationValidator("RegularExpressionPattern",function(e,t){const n=e.get(t);let r=!0;if(!m().isNonEmptyString(n))return a().getFormElementPropertyValidatorDefinition("RegularExpressionPattern").errorMessage||"invalid value";try{const i=n.match(/^\/(.*)\/[gmixsuUAJD]*$/);i!==null?new RegExp(i[1]):r=!1}catch{r=!1}if(!r)return a().getFormElementPropertyValidatorDefinition("RegularExpressionPattern").errorMessage||"invalid value"}),a().addPropertyValidationValidator("ItemCount",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const r=e.get(t).split(",").filter(c=>c!==""),{minItems:i,maxItems:l}=ge(e,t);if(i>0&&r.length1&&r.length>l)return pe(i,l)}),a().addPropertyValidationValidator("IntegerList",function(e,t){if(m().isUndefinedOrNull(e.get(t)))return;const r=e.get(t).split(",").filter(i=>i!=="");for(const i of r)if(isNaN(Number(i)))return a().getFormElementPropertyValidatorDefinition("IntegerList").errorMessage||"invalid value"})}function ge(e,t){const r=a().getFormElementDefinition(e,"editors").find(i=>i.propertyPath===t);return{minItems:r?.minItems??0,maxItems:r?.maxItems??1}}function pe(e,t){const n=a().getFormElementPropertyValidatorDefinition("ItemCount").errorMessage;return n?n.replace("{0}",String(e)).replace("{1}",String(t)):"invalid value"}function Ee(e){let t=[];if(typeof e=="object"&&!Array.isArray(e))for(const r of Object.keys(e))t.push(e[r]);else t=e;if(!Array.isArray(t)){s().publish("view/ready");return}const n=t.length;if(n>0){let r=0;for(let i=0;idocument.querySelector(o().getDomElementDataIdentifierSelector(t));e("buttonHeaderSave")?.addEventListener("click",function(){s().publish("view/header/button/save/clicked",[])}),e("buttonToggleStructure")?.addEventListener("click",function(){e("structureSection")?.classList.toggle("formeditor-inspector-expanded")}),e("buttonExpandInspector")?.addEventListener("click",function(){e("inspectorSection")?.classList.add("formeditor-inspector-expanded")}),e("buttonCollapseInspector")?.addEventListener("click",function(){e("inspectorSection")?.classList.remove("formeditor-inspector-expanded")}),e("buttonFormSettings")?.addEventListener("click",function(){s().publish("view/header/formSettings/clicked",[])}),e("buttonNewPage")?.addEventListener("click",function(){s().publish("view/structure/button/newPage/clicked",["view/insertPages/perform"])}),e("buttonHeaderClose")?.addEventListener("click",function(t){a().getUnsavedContent()&&(t.preventDefault(),s().publish("view/header/button/close/clicked",[]))}),e("buttonHeaderUndo")?.addEventListener("click",function(){s().publish("view/undoButton/clicked",[])}),e("buttonHeaderRedo")?.addEventListener("click",function(){s().publish("view/redoButton/clicked",[])}),e("buttonHeaderViewModeAbstract")?.addEventListener("click",function(){s().publish("view/viewModeButton/abstract/clicked",[])}),e("buttonHeaderViewModePreview")?.addEventListener("click",function(){s().publish("view/viewModeButton/preview/clicked",[])}),e("structureRootContainer")?.addEventListener("click",function(){s().publish("view/structure/root/selected")}),e("buttonHeaderPaginationNext")?.addEventListener("click",function(){s().publish("view/paginationNext/clicked",[])}),e("buttonHeaderPaginationPrevious")?.addEventListener("click",function(){s().publish("view/paginationPrevious/clicked",[])})}function a(){return I}function o(e){return m().isUndefinedOrNull(e)?N.setConfiguration(O):N.setConfiguration(e)}function g(e,t){return a().getFormElementDefinition(e,t)}function Ce(){return de(O)}function ye(){return W}function we(e){W=!!e}function f(){return _}function L(){f().renew(),s().publish("view/structure/renew/postProcess")}function Pe(e){f().selectTreeNode(e)}function G(e){f().getTreeNode(e)?.classList.add(o().getDomElementClassName("selectedFormElement"))}function Ae(e){f().getTreeNode(e)?.classList.remove(o().getDomElementClassName("selectedFormElement"))}function J(){const e=f().getTreeDomElement();e&&e.querySelectorAll(o().getDomElementClassName("selectedFormElement",!0)).forEach(t=>t.classList.remove(o().getDomElementClassName("selectedFormElement")))}function M(){return document.querySelector(o().getDomElementDataAttribute("identifier","bracesWithKeyValue",[o().getDomElementDataAttributeValue("structureRootContainer")]))}function Q(){return document.querySelector(o().getDomElementDataAttribute("identifier","bracesWithKeyValue",[o().getDomElementDataAttributeValue("structureRootElement")]))}function X(){M()?.classList.remove(o().getDomElementClassName("selectedRootFormElement"))}function Y(){M()?.classList.add(o().getDomElementClassName("selectedRootFormElement"))}function Z(e){if(m().isUndefinedOrNull(e)){const n=document.createElement("span");n.textContent=u().get("label")?u().get("label"):u().get("identifier"),e=n.textContent}const t=Q();t&&(t.textContent=e)}function Fe(){f().clearAllValidationErrors();const e=a().validateFormElementRecursive(u());for(let t=0,n=e.length;t0){r=!0;break}if(r){const i=e[t].formElementIdentifierPath;f().setNodeValidationError(i,!0);const l=i.split("/");for(;l.pop();){const c=l.join("/");c&&f().setNodeChildHasError(c,!0)}}}}function D(){return j}function Ne(e){m().isUndefinedOrNull(e)&&(e=v()),D().showRemoveFormElementModal(e)}function Ie(e,t,n){m().isUndefinedOrNull(n)&&(n=v()),D().showRemoveCollectionElementModal(e,t,n)}function Ve(){D().showCloseConfirmationModal()}function Le(e,t){D().showInsertElementsModal(e,t)}function Me(e){D().showInsertPagesModal(e)}function Re(){const e=a().validateFormElementRecursive(u());D().showValidationErrorsModal(e)}function R(){return z}function H(e){R().renderEditors(e)}function He(){const e=document.querySelector(o().getDomElementDataIdentifierSelector("inspectorSection"));e&&e.querySelector("input, select, textarea")?.focus()}function Te(){document.querySelector(o().getDomElementDataIdentifierSelector("inspectorSection"))?.classList.add("formeditor-inspector-expanded")}function Ue(e,t){R().renderCollectionElementEditors(e,t)}function d(){return K}function ee(e){d().setStageHeadline(e)}function te(){d().getStagePanelDomElement()?.classList.add(o().getDomElementClassName("selectedStagePanel"))}function ne(){d().getStagePanelDomElement()?.classList.remove(o().getDomElementClassName("selectedStagePanel"))}function T(){d().renderPagination()}function xe(){d().renderUndoRedo()}function oe(){P(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderViewModeAbstract"))),x(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderViewModePreview"))),document.querySelector(o().getDomElementDataIdentifierSelector("moduleWrapper"))?.classList.add(o().getDomElementClassName("viewModeAbstract")),document.querySelector(o().getDomElementDataIdentifierSelector("moduleWrapper"))?.classList.remove(o().getDomElementClassName("viewModePreview"));const e=n=>{d().renderAbstractStageArea(void 0,n)},t=()=>{const n=g(v(),void 0);d().getAllFormElementDomElements().forEach(function(r){r.addEventListener("mouseenter",function(){d().getAllFormElementDomElements().forEach(i=>{i.parentElement?.classList.remove(o().getDomElementClassName("sortableHover"))}),r.parentElement?.classList.contains(o().getDomElementClassName("formElementIsComposit"))&&!r.parentElement?.classList.contains(o().getDomElementClassName("formElementIsTopLevel"))&&r.parentElement?.classList.add(o().getDomElementClassName("sortableHover"))})}),n._isTopLevelFormElement&&!n._isCompositeFormElement&&a().isRootFormElementSelected(),U(),s().publish("view/stage/abstract/render/postProcess")};e(function(){s().publish("view/stage/abstract/render/preProcess"),t(),s().publish("view/stage/abstract/render/postProcess")})}function qe(e){P(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderViewModePreview"))),x(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderViewModeAbstract"))),document.querySelector(o().getDomElementDataIdentifierSelector("moduleWrapper"))?.classList.add(o().getDomElementClassName("viewModePreview")),document.querySelector(o().getDomElementDataIdentifierSelector("moduleWrapper"))?.classList.remove(o().getDomElementClassName("viewModeAbstract")),d().renderPreviewStageArea(e),s().publish("view/stage/preview/render/postProcess")}function ke(){const e=a().validateFormElementRecursive(u());for(let t=0,n=e.length;t0){r=!0;break}if(r&&t>0){const i=d().getAbstractViewFormElementDomElement(e[t].formElementIdentifierPath),l=i.querySelector("typo3-form-form-element-stage-item");l&&"invalid"in l&&(l.invalid=!0),ae(i)}}}function Be(e,t,n){const r=a().createAndAddFormElement(e,t);return n||s().publish("view/formElement/inserted",[r]),r}function S(e,t,n,r){const i=a().moveFormElement(e,t,n,!1);return r||s().publish("view/formElement/moved",[i]),i}function Oe(e,t){let n;return m().isUndefinedOrNull(e)&&(e=v()),g(e,"_isTopLevelFormElement")&&g(e,"_isCompositeFormElement")&&u().get("renderables").length===1?w.error(g(u(),"modalRemoveElementLastAvailablePageFlashMessageTitle"),g(u(),"modalRemoveElementLastAvailablePageFlashMessageMessage"),2):(n=a().removeFormElement(e,!1),t||s().publish("view/formElement/removed",[n])),n}function We(e,t,n,r,i,l){a().createAndAddPropertyCollectionElement(e,t,n,r,i),l||s().publish("view/collectionElement/new/added",[e,t,n,r,i])}function _e(e,t,n,r,i,l){m().isUndefinedOrNull(i)&&(i=v()),a().movePropertyCollectionElement(e,t,n,r,i,!1),l||s().publish("view/collectionElement/moved",[e,t,n,r,i])}function je(e,t,n,r){let i,l;a().removePropertyCollectionElement(e,t,n);const c=a().getPropertyCollectionElementConfiguration(e,t);if(Array.isArray(c.editors)){for(let p=0,se=c.editors.length;p{n.parentElement?.classList.remove(o().getDomElementClassName("selectedCompositFormElement"))}),!e._isTopLevelFormElement&&e._isCompositeFormElement&&t?.parentElement?.classList.add(o().getDomElementClassName("selectedCompositFormElement"))}}function re(e){E(typeof e=="number",'Invalid parameter "pageIndex"',1478651732),E(e>=0,'Invalid parameter "pageIndex"',1478651733),E(ee.classList.remove(o().getDomElementClassName("selectedFormElement"))),ne(),d().getAllFormElementDomElements().forEach(e=>e.parentElement?.classList.remove(o().getDomElementClassName("sortableHover")))}function ze(){ee(),Z(),oe(),L(),Y(),H(),T(),le(document.querySelector(o().getDomElementDataIdentifierSelector("moduleLoadingIndicator"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("moduleWrapper"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("inspectorSection"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderSave"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderClose"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderUndo"))),h(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderRedo"))),P(document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderViewModeAbstract")))}function Ke(e,t){t?.classList.remove(o().getDomElementClassName("sortableHover"))}function $e(e,t,n){d().getAllFormElementDomElements().forEach(r=>{r.parentElement?.classList.remove(o().getDomElementClassName("sortableHover"))}),n&&d().getAbstractViewParentFormElementWithinDomElement(e)?.parentElement?.classList.add(o().getDomElementClassName("sortableHover"))}function Ge(e,t,n,r){let i,l;r?i=S(t,"before",r):n?i=S(t,"after",n):(l=d().getAbstractViewParentFormElementIdentifierPathWithinDomElement(e),l?i=S(t,"inside",l):E(!1,"Next element, previous or parent element need to be set.",1472502237)),d().getAbstractViewFormElementWithinDomElement(e)?.setAttribute(o().getDomElementDataAttribute("elementIdentifier"),i.get("__identifierPath"))}function Je(e,t,n){f().getAllTreeNodes().forEach(r=>r.parentElement?.classList.remove(o().getDomElementClassName("sortableHover"))),d().getAllFormElementDomElements().forEach(r=>r.parentElement?.classList.remove(o().getDomElementClassName("sortableHover"))),n&&(f().getParentTreeNodeWithinDomElement(e)?.parentElement?.classList.add(o().getDomElementClassName("sortableHover")),d().getAbstractViewFormElementDomElement(n)?.parentElement?.classList.add(o().getDomElementClassName("sortableHover")))}function Qe(e,t,n,r){let i,l;r?i=S(t,"before",r):n?i=S(t,"after",n):(l=f().getParentTreeNodeIdentifierPathWithinDomElement(e),l?i=S(t,"inside",l):a().assert(!1,"Next element, previous or parent element need to be set.",1479048646)),f().getTreeNodeWithinDomElement(e)?.setAttribute(o().getDomElementDataAttribute("elementIdentifier"),i.get("__identifierPath"))}function Xe(){const e=document.querySelector(o().getDomElementDataIdentifierSelector("buttonHeaderClose"));document.location.href=e?.href??""}function ae(e,t){a().getUtility().isUndefinedOrNull(t)?e?.classList.replace("panel-default","panel-danger"):e?.classList.add(o().getDomElementClassName(t))}function Ye(e,t){a().getUtility().isUndefinedOrNull(t)?e?.classList.replace("panel-danger","panel-default"):e?.classList.remove(o().getDomElementClassName(t))}function h(e){e?.classList.remove(o().getDomElementClassName("hidden")),e&&(e.style.display="")}function le(e){e?.classList.add(o().getDomElementClassName("hidden")),e&&(e.style.display="none")}function Ze(e){e&&(e.disabled=!1),e?.classList.remove(o().getDomElementClassName("disabled"))}function et(e){e&&(e.disabled=!0),e?.classList.add(o().getDomElementClassName("disabled"))}function P(e){e?.classList.add(o().getDomElementClassName("active"))}function x(e){e?.classList.remove(o().getDomElementClassName("active"))}function tt(){y.getIcon(o().getDomElementDataAttributeValue("iconSaveSpinner"),y.sizes.small).then(function(e){const t=document.querySelector(o().getDomElementDataIdentifierSelector("iconSave"));if(t){const n=document.createElement("div");n.innerHTML=e,t.replaceWith(n.firstElementChild??n)}})}function nt(){y.getIcon(o().getDomElementDataAttributeValue("iconSave"),y.sizes.small).then(function(e){const t=document.querySelector(o().getDomElementDataIdentifierSelector("iconSaveSpinner"));if(t){const n=document.createElement("div");n.innerHTML=e,t.replaceWith(n.firstElementChild??n)}})}function ot(){w.success(g(u(),"saveSuccessFlashMessageTitle"),g(u(),"saveSuccessFlashMessageMessage"),2)}function rt(e){w.error(g(u(),"saveErrorFlashMessageTitle"),g(u(),"saveErrorFlashMessageMessage")+" "+e.message)}function it(e,t){w.error(e,t,2)}function at(e,t){I=e,N.bootstrap(I),ve(),be(),De(),Se(),he(),fe(),Ee(t)}export{ke as addAbstractViewValidationResults,te as addStagePanelSelection,Y as addStructureRootElementSelection,G as addStructureSelection,Fe as addStructureValidationResults,at as bootstrap,Xe as closeEditor,Be as createAndAddFormElement,We as createAndAddPropertyCollectionElement,et as disableButton,Ze as enableButton,He as focusFirstInspectorInput,Ce as getConfiguration,a as getFormEditorApp,g as getFormElementDefinition,o as getHelper,R as getInspector,D as getModals,ye as getPreviewMode,d as getStage,f as getStructure,M as getStructureRootContainer,Q as getStructureRootElement,le as hideComponent,S as moveFormElement,_e as movePropertyCollectionElement,$e as onAbstractViewDndChangeBatch,Ke as onAbstractViewDndStartBatch,Ge as onAbstractViewDndUpdateBatch,Je as onStructureDndChangeBatch,Qe as onStructureDndUpdateBatch,ze as onViewReadyBatch,U as refreshSelectedElementItemsBatch,ie as removeAllStageElementSelectionsBatch,J as removeAllStructureSelections,x as removeButtonActive,Ye as removeElementValidationErrorClass,Oe as removeFormElement,je as removePropertyCollectionElement,ne as removeStagePanelSelection,X as removeStructureRootElementSelection,Ae as removeStructureSelection,oe as renderAbstractStageArea,Ue as renderInspectorCollectionElementEditors,H as renderInspectorEditors,T as renderPagination,qe as renderPreviewStageArea,xe as renderUndoRedo,L as renewStructure,re as selectPageBatch,Pe as selectStructureNode,P as setButtonActive,ae as setElementValidationErrorClass,we as setPreviewMode,ee as setStageHeadline,Z as setStructureRootElementTitle,Ve as showCloseConfirmationModal,h as showComponent,it as showErrorFlashMessage,Le as showInsertElementsModal,Me as showInsertPagesModal,Te as showInspectorSidebar,Ie as showRemoveCollectionElementModal,Ne as showRemoveFormElementModal,nt as showSaveButtonSaveIcon,tt as showSaveButtonSpinnerIcon,rt as showSaveErrorMessage,ot as showSaveSuccessMessage,Re as showValidationErrorsModal}; diff --git a/Resources/Public/JavaScript/backend/form-manager.js b/Resources/Public/JavaScript/backend/form-manager.js new file mode 100644 index 0000000..5132ea5 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-manager.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +function n(r,t,i){if(typeof r=="function"&&(r=r()!==!1),!r)throw t=t||"Assertion failed",i&&(t=t+" ("+i+")"),typeof Error<"u"?new Error(t):t}class s{constructor(t,i){this.isRunning=!1,this.configuration=t,this.viewModel=i}assert(t,i,e){n(t,i,e)}getPrototypes(){return Array.isArray(this.configuration.selectablePrototypesConfiguration)?this.configuration.selectablePrototypesConfiguration.map(t=>({label:t.label,value:t.identifier})):[]}getTemplatesForPrototype(t){if(n(typeof t=="string",'Invalid parameter "prototypeName"',1475945286),!Array.isArray(this.configuration.selectablePrototypesConfiguration))return[];const i=[];return this.configuration.selectablePrototypesConfiguration.forEach(e=>{Array.isArray(e.newFormTemplates)&&e.identifier===t&&e.newFormTemplates.forEach(a=>{i.push({label:a.label,value:a.templatePath})})}),i}getAccessibleStorageAdapters(){return Array.isArray(this.configuration.accessibleStorageAdapters)?this.configuration.accessibleStorageAdapters:[]}getAccessibleStorageLocationsForAdapter(t){const i=this.configuration.accessibleStorageAdapters?.find(e=>e.typeIdentifier===t.typeIdentifier);return!i||!i.options?.allowedStorageLocations?[]:i.options.allowedStorageLocations}getAjaxEndpoint(t){return n(typeof this.configuration.endpoints[t]<"u","Endpoint "+t+" does not exist",1477506508),this.configuration.endpoints[t]}run(){if(this.isRunning)throw"You can not run the app twice (1475942618)";return this.bootstrap(),this.isRunning=!0,this}viewSetup(){n(typeof this.viewModel.bootstrap=="function",'The view model does not implement the method "bootstrap"',1475942906),this.viewModel.bootstrap(this)}bootstrap(){this.configuration=this.configuration||{},n(typeof this.configuration.endpoints=="object",'Invalid parameter "endpoints"',1477506504),this.viewSetup()}}let o=null;function f(r,t){return o===null&&(o=new s(r,t)),o}export{s as FormManager,n as assert,f as getInstance}; diff --git a/Resources/Public/JavaScript/backend/form-manager/main.js b/Resources/Public/JavaScript/backend/form-manager/main.js new file mode 100644 index 0000000..a06ccab --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-manager/main.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import t from"@typo3/core/document-service.js";import o from"@typo3/core/event/regular-event.js";class a{constructor(){t.ready().then(()=>{const e=document.getElementById("search_field");if(e!==null){const r=e.value!=="";new o("search",()=>{e.value===""&&r&&e.closest("form").requestSubmit()}).bindTo(e)}})}}var n=new a;export{n as default}; diff --git a/Resources/Public/JavaScript/backend/form-manager/view-model.js b/Resources/Public/JavaScript/backend/form-manager/view-model.js new file mode 100644 index 0000000..0e359f6 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-manager/view-model.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import l from"@typo3/backend/modal.js";import h from"@typo3/backend/severity.js";import v from"@typo3/backend/icons.js";import b from"@typo3/backend/notification.js";import z from"@typo3/core/security-utility.js";import M from"@typo3/core/ajax/ajax-request.js";import{AjaxResponse as L}from"@typo3/core/ajax/ajax-response.js";import{SeverityEnum as w}from"@typo3/backend/enum/severity.js";import{topLevelModuleImport as y}from"@typo3/backend/utility/top-level-module-import.js";import{html as k}from"lit";import t from"~labels/form.form_manager_javascript";const u=new z;var f;(function(e){e.newFormModalTrigger='[data-identifier="newForm"]',e.duplicateFormModalTrigger='[data-identifier="duplicateForm"]',e.removeFormModalTrigger='[data-identifier="removeForm"]',e.showReferences='[data-identifier="showReferences"]',e.referenceLink='[data-identifier="referenceLink"]'})(f||(f={}));function S(e){document.querySelectorAll(f.newFormModalTrigger).forEach(r=>{r.addEventListener("click",async c=>{c.preventDefault(),await y("@typo3/form/backend/form-wizard/form-wizard.js");const n=k``;l.advanced({title:t.get("formManager.newFormWizard.step1.title"),content:n,severity:w.notice,size:l.sizes.medium,staticBackdrop:!0,buttons:[]})})})}function T(e){document.querySelectorAll(f.removeFormModalTrigger).forEach(r=>{r.addEventListener("click",async c=>{const n=[];c.preventDefault(),n.push({text:t.get("formManager.cancel"),active:!0,btnClass:"btn-default",name:"cancel",trigger:function(i,o){o.hideModal()}}),n.push({text:t.get("formManager.remove_form"),active:!0,btnClass:"btn-danger",name:"createform",trigger:function(i,o){new M(e.getAjaxEndpoint("delete")).post({formPersistenceIdentifier:r.dataset.formPersistenceIdentifier}).then(async s=>{const d=await s.resolve();d.status==="success"?document.location=d.url:b.error(d.title,d.message),o.hideModal()})}}),l.show(t.get("formManager.remove_form_title"),t.get("formManager.remove_form_message",{0:r.dataset.formName}),h.error,n)})})}function x(e){document.querySelectorAll(f.duplicateFormModalTrigger).forEach(r=>{r.addEventListener("click",async c=>{c.preventDefault(),await y("@typo3/form/backend/form-wizard/form-wizard.js");const n={name:r.dataset.formName,persistenceIdentifier:r.dataset.formPersistenceIdentifier},i=k``;l.advanced({title:t.get("formManager.duplicateFormWizard.step1.title",{0:r.dataset.formName}),content:i,severity:w.notice,size:l.sizes.medium,staticBackdrop:!0,buttons:[]})})})}function I(e){document.querySelectorAll(f.showReferences).forEach(r=>{r.addEventListener("click",c=>{c.preventDefault();const n=e.getAjaxEndpoint("references")+"&formPersistenceIdentifier="+r.dataset.formPersistenceIdentifier;new M(n).get().then(async i=>{const o=await i.resolve();let s;const d=[];d.push({text:t.get("formManager.cancel"),active:!0,btnClass:"btn-default",name:"cancel",trigger:function(a,m){m.hideModal()}});const E=o.references.length,F=await v.getIcon("actions-open",v.sizes.small);if(E>0){s='

    '+t.get("formManager.references.headline")+'

    ";for(let a=0,m=o.references.length;a";s+="
    '+t.get("formManager.table.field.title")+""+t.get("formManager.table.field.uid")+''+t.get("formManager.table.field.control")+"
    '+o.references[a].recordIcon+''+u.encodeHtml(o.references[a].recordTitle)+""+u.encodeHtml(o.references[a].recordUid)+'
    "}else s="

    "+t.get("formManager.references.title",{0:u.encodeHtml(o.formPersistenceIdentifier)})+"

    "+t.get("formManager.no_references")+"
    ";const g=document.createElement("template");g.innerHTML=s;const p=g.content;p.querySelectorAll(f.referenceLink).forEach(a=>{a.addEventListener("click",m=>{m.preventDefault(),l.currentModal.hideModal(),document.location=m.currentTarget.href})}),l.show(t.get("formManager.references.title",{0:r.dataset.formName}),p,h.notice,d)}).catch(i=>{i instanceof L&&b.error(i.response.statusText,String(i.response.status),2)})})})}function j(e){T(e),S(e),x(e),I(e)}export{j as bootstrap}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/finisher/create-form-submission-service.js b/Resources/Public/JavaScript/backend/form-wizard/finisher/create-form-submission-service.js new file mode 100644 index 0000000..d220a82 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/finisher/create-form-submission-service.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import o from"@typo3/core/ajax/ajax-request.js";import s from"~labels/form.form_manager_javascript";class a{constructor(e){this.context=e}async execute(){const e=this.context.getDataStore(),r=this.context.formManager.getAjaxEndpoint("create"),t=await(await new o(r).post({formName:e.settings.formName,templatePath:e.settings.template,prototypeName:e.settings.prototype,storage:e.storage.typeIdentifier,storageLocation:e.settings.storageLocation})).resolve();return t?.status==="success"?{success:!0,finisher:{identifier:"redirect",module:"@typo3/backend/wizard/finisher/redirect-finisher.js",data:{url:t.url},labels:{successTitle:s.get("formManager.finisher.redirect.success.title"),successDescription:s.get("formManager.finisher.redirect.success.description")}}}:{success:!1,errors:[t?.message]}}}export{a as CreateFormSubmissionService}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/finisher/duplicate-form-submission-service.js b/Resources/Public/JavaScript/backend/form-wizard/finisher/duplicate-form-submission-service.js new file mode 100644 index 0000000..d75869c --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/finisher/duplicate-form-submission-service.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import i from"@typo3/core/ajax/ajax-request.js";import r from"~labels/form.form_manager_javascript";class o{constructor(e,s){this.context=e,this.formPersistenceIdentifier=s}async execute(){const e=this.context.getDataStore(),s=this.context.formManager.getAjaxEndpoint("duplicate"),t=await(await new i(s).post({formName:e.settings.formName,storage:e.storage.typeIdentifier,storageLocation:e.settings.storageLocation,formPersistenceIdentifier:this.formPersistenceIdentifier})).resolve();return t?.status==="success"?{success:!0,finisher:{identifier:"redirect",module:"@typo3/backend/wizard/finisher/redirect-finisher.js",data:{url:t.url},labels:{successTitle:r.get("formManager.finisher.redirect.success.title"),successDescription:r.get("formManager.finisher.redirect.success.description")}}}:{success:!1,errors:[t?.message]}}}export{o as DuplicateFormSubmissionService}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/form-wizard.js b/Resources/Public/JavaScript/backend/form-wizard/form-wizard.js new file mode 100644 index 0000000..e580c74 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/form-wizard.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import"@typo3/backend/wizard/wizard.js";import{state as d,property as l,query as S,customElement as w}from"lit/decorators.js";import u from"@typo3/form/backend/form-wizard/steps/settings-step.js";import{LitElement as g,html as f}from"lit";import c from"~labels/form.form_manager_javascript";import{StepSummaryEvent as h}from"@typo3/backend/wizard/events/step-summary-event.js";import{DuplicateFormSubmissionService as v}from"@typo3/form/backend/form-wizard/finisher/duplicate-form-submission-service.js";import y from"@typo3/form/backend/form-wizard/steps/mode-step.js";import{CreateFormSubmissionService as z}from"@typo3/form/backend/form-wizard/finisher/create-form-submission-service.js";import{FormManager as M}from"@typo3/form/backend/form-manager.js";import{AutoAdvanceEvent as F}from"@typo3/backend/wizard/events/auto-advance-event.js";import{StorageStep as b}from"@typo3/form/backend/form-wizard/steps/storage-step.js";var a=function(o,t,e,s){var n=arguments.length,i=n<3?t:s===null?s=Object.getOwnPropertyDescriptor(t,e):s,m;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(o,t,e,s);else for(var p=o.length-1;p>=0;p--)(m=o[p])&&(i=(n<3?m(i):n>3?m(t,e,i):m(t,e))||i);return n>3&&i&&Object.defineProperty(t,e,i),i};let r=class extends g{constructor(){super(...arguments),this.steps=[],this.errorMessage=null,this.duplicateForm=null}connectedCallback(){super.connectedCallback(),this.addEventListener(h.eventName,this.handleStepSummary)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(h.eventName,this.handleStepSummary)}firstUpdated(t){if(super.firstUpdated(t),this.formManager.getAccessibleStorageAdapters().length<1){this.errorMessage=c.get("formManager.newFormWizard.step1.noStorages");return}const e={wizard:this.wizard,formManager:this.formManager,getStoreData:this.wizard.getStoreData.bind(this.wizard),setStoreData:this.wizard.setStoreData.bind(this.wizard),clearStoreData:this.wizard.clearStoreData.bind(this.wizard),getDataStore:this.wizard.getDataStore.bind(this.wizard),dispatchAutoAdvance:()=>this.wizard.dispatchEvent(new F)};this.duplicateForm!=null?(this.steps=[new b(e),new u(e)],this.submissionService=new v(e,this.duplicateForm.persistenceIdentifier)):(this.steps=[new y(e),new b(e),new u(e)],this.submissionService=new z(e))}createRenderRoot(){return this}render(){return this.errorMessage?this.wizard.renderError(this.errorMessage):f``}handleStepSummary(t){this.duplicateForm!==null&&(t.detail.summaryData=[{label:c.get("formManager.form_copied"),value:f`${this.duplicateForm.name}`},...t.detail.summaryData])}};a([d()],r.prototype,"steps",void 0),a([d()],r.prototype,"submissionService",void 0),a([d()],r.prototype,"errorMessage",void 0),a([l({type:M,attribute:!1})],r.prototype,"formManager",void 0),a([l({type:Object,attribute:!1})],r.prototype,"duplicateForm",void 0),a([S("typo3-backend-wizard")],r.prototype,"wizard",void 0),r=a([w("typo3-backend-form-wizard")],r);export{r as FormWizard}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/steps/mode-step.js b/Resources/Public/JavaScript/backend/form-wizard/steps/mode-step.js new file mode 100644 index 0000000..88fa609 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/steps/mode-step.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{html as s}from"lit";import{live as l}from"lit/directives/live.js";import{unsafeHTML as c}from"lit/directives/unsafe-html.js";import t from"~labels/form.form_manager_javascript";var a;(function(i){i.Blank="blank",i.Predefined="predefined"})(a||(a={}));class n{constructor(e){this.context=e,this.key="mode",this.title=t.get("formManager.newFormWizard.step1.progressLabel"),this.autoAdvance=!0,this.selectedMode=null,this.modes=[{key:a.Blank,label:t.get("formManager.blankForm.label"),description:t.get("formManager.blankForm.description"),iconIdentifier:"apps-pagetree-page-default"},{key:a.Predefined,label:t.get("formManager.predefinedForm.label"),description:t.get("formManager.predefinedForm.description"),iconIdentifier:"form-page"}]}isComplete(){return this.getValue()!==null}render(){return this.getValue()==null&&this.modes.length>0&&this.setValue(this.modes[0].key),s`
    ${this.modes.map(e=>s`
    this.setValue(e.key)}>
    `)}
    `}reset(){this.setValue(null),this.context.clearStoreData(this.key)}getValue(){return this.selectedMode}setValue(e){this.selectedMode=e,this.context.wizard.requestUpdate()}beforeAdvance(){this.context.setStoreData(this.key,this.getValue())}getSummaryData(){const e=this.context.getStoreData(this.key);if(!e)return[];const r=this.modes.find(o=>o.key===e);return r?[{label:t.get("formManager.newFormWizard.step.modes.summary.title"),value:s`${r.label}`}]:[]}}export{a as MODE,n as ModeStep,n as default}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/steps/settings-step.js b/Resources/Public/JavaScript/backend/form-wizard/steps/settings-step.js new file mode 100644 index 0000000..2eae5b8 --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/steps/settings-step.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{html as r,nothing as i}from"lit";import{MODE as m}from"@typo3/form/backend/form-wizard/steps/mode-step.js";import o from"~labels/form.form_manager_javascript";class c{constructor(e){this.context=e,this.key="settings",this.title=o.get("formManager.newFormWizard.step2.title"),this.autoAdvance=!0,this.data={formName:"",storageLocation:"",prototype:"",template:""},this.reset()}isComplete(){return this.getValue()?.formName!==""}render(){return r`${this.renderPredefinedFormFields()} ${this.renderSavePath()} ${this.renderFormNameInput()}`}reset(){this.setValue({formName:"",storageLocation:""}),this.setPrototype(this.context.formManager.getPrototypes()[0]?.value??""),this.context.clearStoreData(this.key)}getValue(){return this.data}setValue(e){this.data={...this.data,...e},this.context.wizard.requestUpdate()}beforeAdvance(){this.context.setStoreData(this.key,this.getValue())}getSummaryData(){const e=this.context.getStoreData(this.key),a=this.context.formManager.getPrototypes().find(s=>s.value===e.prototype)?.label,n=this.context.formManager.getTemplatesForPrototype(e.prototype).find(s=>s.value===e.template)?.label,l=this.context.getStoreData("mode")===m.Predefined,t=this.context.getStoreData("storage"),g=(t?this.context.formManager.getAccessibleStorageLocationsForAdapter(t):[]).find(s=>s.value===e.storageLocation)?.label??e.storageLocation;return[...l?[{value:a,label:o.get("formManager.form_prototype")},{value:n,label:o.get("formManager.form_template")}]:[],{value:e.formName,label:o.get("formManager.form_name")},{value:g,label:o.get("formManager.form_storageLocation")}]}renderSavePath(){const e=this.context.formManager.getAccessibleStorageLocationsForAdapter(this.context.getStoreData("storage"))??[];return e.length<=1?(this.setValue({storageLocation:e[0]?.value??""}),i):(!this.data.storageLocation&&e.length>0&&this.setValue({storageLocation:e[0].value}),r`
    ${o.get("formManager.form_storageLocation_description")}
    `)}renderFormNameInput(){return r`
    ${o.get("formManager.form_name_description")}
    this.setValue({formName:e.target.value})}>
    `}renderPredefinedFormFields(){const e=this.context.formManager.getPrototypes()??[];if(this.context.getStoreData("mode")!==m.Predefined||e.length<1)return i;const a=this.data.prototype,n=this.context.formManager.getTemplatesForPrototype(a);let l=i;return n.length>0&&(l=r`
    `),r`
    ${l}`}setPrototype(e){const a=this.context.formManager.getTemplatesForPrototype(e);this.setValue({prototype:e,template:a[0]?.value??""})}}export{c as SettingsStep,c as default}; diff --git a/Resources/Public/JavaScript/backend/form-wizard/steps/storage-step.js b/Resources/Public/JavaScript/backend/form-wizard/steps/storage-step.js new file mode 100644 index 0000000..1870c4d --- /dev/null +++ b/Resources/Public/JavaScript/backend/form-wizard/steps/storage-step.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{html as s}from"lit";import{live as o}from"lit/directives/live.js";import{unsafeHTML as n}from"lit/directives/unsafe-html.js";import a from"~labels/form.form_manager_javascript";class r{constructor(e){this.context=e,this.key="storage",this.title=a.get("formManager.newFormWizard.step.storages.progressLabel"),this.autoAdvance=!0,this.hasDispatchedAutoAdvance=!1,this.selectedStorage=null}isComplete(){return this.getValue()!==null}render(){const e=this.context.formManager.getAccessibleStorageAdapters();let i=!1;return this.getValue()==null&&e.length>0&&(this.setValue(e[0]),e.length===1&&(i=!0)),i&&!this.hasDispatchedAutoAdvance?(this.hasDispatchedAutoAdvance=!0,this.context.dispatchAutoAdvance(),this.context.wizard.renderLoader()):s`

    ${a.get("formManager.newFormWizard.step.storages.title")}

    ${a.get("formManager.newFormWizard.step.storages.description")}

    ${e.map(t=>s`
    this.setValue(t)}>
    `)}
    `}reset(){this.setValue(null),this.context.clearStoreData(this.key)}getValue(){return this.selectedStorage}setValue(e){this.selectedStorage=e,this.context.wizard.requestUpdate()}beforeAdvance(){this.context.setStoreData(this.key,this.getValue())}getSummaryData(){const e=this.context.getStoreData(this.key);return e?[{label:a.get("formManager.newFormWizard.step.storages.summary.title"),value:s`${e.label}`}]:[]}}export{r as StorageStep,r as default}; diff --git a/Resources/Public/JavaScript/backend/helper.js b/Resources/Public/JavaScript/backend/helper.js new file mode 100644 index 0000000..43eac5b --- /dev/null +++ b/Resources/Public/JavaScript/backend/helper.js @@ -0,0 +1,13 @@ +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ +import{loadModule as a}from"@typo3/core/java-script-item-processor.js";import r from"@typo3/core/document-service.js";class l{static dispatchFormEditor(o,t){r.ready().then(()=>{Promise.all([a(o.app),a(o.mediator),a(o.viewModel)]).then(e=>((d,i,n)=>{window.TYPO3.FORMEDITOR_APP=d.getInstance(t,i,n).run()})(...e))})}static dispatchFormManager(o,t){r.ready().then(()=>{Promise.all([a(o.app),a(o.viewModel)]).then(e=>((d,i)=>{window.TYPO3.FORMMANAGER_APP=d.getInstance(t,i).run()})(...e))})}}export{l as Helper}; diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..3559407 --- /dev/null +++ b/composer.json @@ -0,0 +1,64 @@ +{ + "name": "typo3/cms-form", + "type": "typo3-cms-framework", + "description": "TYPO3 CMS Form - Flexible TYPO3 frontend form framework that comes with a backend editor interface.", + "homepage": "https://typo3.community/", + "funding": [ + { + "type": "membership", + "url": "https://typo3.org/membership" + } + ], + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "TYPO3 Core Team", + "email": "typo3cms@typo3.org", + "role": "Developer" + } + ], + "support": { + "issues": "https://forge.typo3.org/issues/", + "forum": "https://talk.typo3.org/", + "source": "https://github.com/TYPO3/typo3/", + "docs": "https://docs.typo3.org/c/typo3/cms-form/main/en-us/", + "rss": "https://news.typo3.com/rss/", + "chat": "https://typo3.community/meet/slack/", + "security": "https://typo3.org/security/" + }, + "config": { + "sort-packages": true + }, + "require": { + "psr/http-message": "^1.1 || ^2.0", + "symfony/expression-language": "^7.4.8", + "typo3/cms-core": "15.0.*@dev", + "typo3/cms-frontend": "15.0.*@dev" + }, + "suggest": { + "typo3/cms-filelist": "Listing of files in the directory", + "typo3/cms-impexp": "Import and Export of records from TYPO3 in a custom serialized format (.T3D) for data exchange with other TYPO3 systems.", + "typo3/cms-lowlevel": "To display the YAML configuration in the configuration module" + }, + "conflict": { + "typo3/cms": "*" + }, + "extra": { + "branch-alias": { + "dev-main": "15.0.x-dev" + }, + "typo3/cms": { + "Package": { + "partOfFactoryDefault": true + }, + "extension-key": "form" + } + }, + "autoload": { + "psr-4": { + "TYPO3\\CMS\\Form\\": "Classes/" + } + } +} diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..1dafd0d --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,37 @@ +beforeAddSysFileRecordOnImport'; +} + +// Register RTE presets for form extension +// form-label: Simple formatting for labels (bold, italic, link) +if (empty($GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['form-label'])) { + $GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['form-label'] = 'EXT:form/Configuration/RTE/FormLabel.yaml'; +} +// form-content: Extended formatting for content fields (includes lists) +if (empty($GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['form-content'])) { + $GLOBALS['TYPO3_CONF_VARS']['RTE']['Presets']['form-content'] = 'EXT:form/Configuration/RTE/FormContent.yaml'; +} + +// Deny direct DataHandler write access to form_definition: only DatabaseStorageAdapter may persist form definitions +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processDatamapClass']['form'] = FormDefinitionDataHandlerHook::class; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['processCmdmapClass']['form'] = FormDefinitionDataHandlerHook::class; + +// Add validation call for input which contains email or form element identifier +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][EmailOrFormElementIdentifier::class] = ''; + +// Register FE plugin +ExtensionUtility::configurePlugin('Form', 'Formframework', [FormFrontendController::class => ['render', 'perform']], [FormFrontendController::class => ['perform']]); diff --git a/ext_tables.sql b/ext_tables.sql new file mode 100644 index 0000000..5de234c --- /dev/null +++ b/ext_tables.sql @@ -0,0 +1,9 @@ +CREATE TABLE sys_refindex ( + # EXT:form BE module related DatabaseService needs this index for "form usage count" lookups + # @todo: Solve differently somehow. It is essentially needed because not all form.yaml + # are FAL resources, but can be provided by extensions, too. See the registered + # softref parser for more details, too. + KEY lookup_string (ref_string(191)), + # Prevent full table scan for queries like "WHERE softref_key='formPersistenceIdentifier' and ref_uid > 0" + KEY idx_softref_key (softref_key,ref_uid) +);
      + +
    • + + + + + + +
    • + +