‪TYPO3CMS  9.5
DataStructureIdentifierHook.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
34 
45 {
46 
50  const ‪L10N_PREFIX = 'LLL:EXT:form/Resources/Private/Language/Database.xlf:';
51 
65  array $fieldTca,
66  string $tableName,
67  string $fieldName,
68  array $row,
69  array $identifier
70  ): array {
71  if ($tableName === 'tt_content' && $fieldName === 'pi_flexform' && $row['CType'] === 'form_formframework') {
72  $currentFlexData = [];
73  if (!empty($row['pi_flexform']) && !\is_array($row['pi_flexform'])) {
74  $currentFlexData = GeneralUtility::xml2array($row['pi_flexform']);
75  }
76 
77  // Add selected form value
78  $identifier['ext-form-persistenceIdentifier'] = '';
79  if (!empty($currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'])) {
80  $identifier['ext-form-persistenceIdentifier'] = $currentFlexData['data']['sDEF']['lDEF']['settings.persistenceIdentifier']['vDEF'];
81  }
82 
83  // Add bool - finisher override active or not
84  $identifier['ext-form-overrideFinishers'] = false;
85  if (
86  isset($currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF'])
87  && (int)$currentFlexData['data']['sDEF']['lDEF']['settings.overrideFinishers']['vDEF'] === 1
88  ) {
89  $identifier['ext-form-overrideFinishers'] = true;
90  }
91  }
92  return $identifier;
93  }
94 
105  public function ‪parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier): array
106  {
107  if (isset($identifier['ext-form-persistenceIdentifier'])) {
108  try {
109  // Add list of existing forms to drop down if we find our key in the identifier
110  $formPersistenceManager = GeneralUtility::makeInstance(ObjectManager::class)->get(FormPersistenceManagerInterface::class);
111  $formIsAccessible = false;
112  foreach ($formPersistenceManager->listForms() as $form) {
113  $invalidFormDefinition = $form['invalid'] ?? false;
114  $hasDeprecatedFileExtension = $form['deprecatedFileExtension'] ?? false;
115 
116  if ($form['location'] === 'storage' && $hasDeprecatedFileExtension) {
117  continue;
118  }
119 
120  if ($form['persistenceIdentifier'] === $identifier['ext-form-persistenceIdentifier']) {
121  $formIsAccessible = true;
122  }
123 
124  if ($invalidFormDefinition || $hasDeprecatedFileExtension) {
125  $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['TCEforms']['config']['items'][] = [
126  $form['name'] . ' (' . $form['persistenceIdentifier'] . ')',
127  $form['persistenceIdentifier'],
128  'overlay-missing'
129  ];
130  } else {
131  $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['TCEforms']['config']['items'][] = [
132  $form['name'] . ' (' . $form['persistenceIdentifier'] . ')',
133  $form['persistenceIdentifier'],
134  'content-form'
135  ];
136  }
137  }
138 
139  if (!empty($identifier['ext-form-persistenceIdentifier']) && !$formIsAccessible) {
140  $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['TCEforms']['config']['items'][] = [
141  sprintf(
142  $this->‪getLanguageService()->sL(self::L10N_PREFIX . 'tt_content.preview.inaccessiblePersistenceIdentifier'),
143  $identifier['ext-form-persistenceIdentifier']
144  ),
145  $identifier['ext-form-persistenceIdentifier'],
146  ];
147  }
148 
149  // If a specific form is selected and if finisher override is active, add finisher sheets
150  if (!empty($identifier['ext-form-persistenceIdentifier'])
151  && $formIsAccessible
152  && isset($identifier['ext-form-overrideFinishers'])
153  && $identifier['ext-form-overrideFinishers'] === true
154  ) {
155  $persistenceIdentifier = $identifier['ext-form-persistenceIdentifier'];
156  $formDefinition = $formPersistenceManager->load($persistenceIdentifier);
157  $newSheets = $this->‪getAdditionalFinisherSheets($persistenceIdentifier, $formDefinition);
159  $dataStructure,
160  $newSheets
161  );
162  }
163  } catch (‪NoSuchFileException $e) {
164  $dataStructure = $this->‪addSelectedPersistenceIdentifier($identifier['ext-form-persistenceIdentifier'], $dataStructure);
166  } catch (‪ParseErrorException $e) {
167  $dataStructure = $this->‪addSelectedPersistenceIdentifier($identifier['ext-form-persistenceIdentifier'], $dataStructure);
169  }
170  }
171  return $dataStructure;
172  }
173 
181  protected function ‪getAdditionalFinisherSheets(string $persistenceIdentifier, array $formDefinition): array
182  {
183  if (!isset($formDefinition['finishers']) || empty($formDefinition['finishers'])) {
184  return [];
185  }
186 
187  $prototypeName = $formDefinition['prototypeName'] ?? 'standard';
188  $prototypeConfiguration = GeneralUtility::makeInstance(ObjectManager::class)
189  ->get(ConfigurationService::class)
190  ->getPrototypeConfiguration($prototypeName);
191 
192  if (!isset($prototypeConfiguration['finishersDefinition']) || empty($prototypeConfiguration['finishersDefinition'])) {
193  return [];
194  }
195 
196  $formIdentifier = $formDefinition['identifier'];
197  $finishersDefinition = $prototypeConfiguration['finishersDefinition'];
198 
199  $sheets = ['sheets' => []];
200  foreach ($formDefinition['finishers'] as $formFinisherDefinition) {
201  $finisherIdentifier = $formFinisherDefinition['identifier'];
202  if (!isset($finishersDefinition[$finisherIdentifier]['FormEngine']['elements'])) {
203  continue;
204  }
205  $sheetIdentifier = $this->‪buildFlexformSheetIdentifier(
206  $persistenceIdentifier,
207  $prototypeName,
208  $formIdentifier,
209  $finisherIdentifier
210  );
211 
212  $finishersDefinition = $this->‪translateFinisherDefinitionByIdentifier(
213  $finisherIdentifier,
214  $finishersDefinition,
215  $prototypeConfiguration
216  );
217 
218  $prototypeFinisherDefinition = $finishersDefinition[$finisherIdentifier];
219  $finisherLabel = $prototypeFinisherDefinition['FormEngine']['label'] ?? '';
220  $sheet = $this->‪initializeNewSheetArray($sheetIdentifier, $finisherLabel);
221 
222  $converterDto = GeneralUtility::makeInstance(
223  ProcessorDto::class,
224  $finisherIdentifier,
225  $prototypeFinisherDefinition,
226  $formFinisherDefinition
227  );
228 
229  // Iterate over all `TYPO3.CMS.Form.prototypes.<prototypeName>.finishersDefinition.<finisherIdentifier>.FormEngine.elements` values
230  // and convert them to FlexForm elements
231  GeneralUtility::makeInstance(ArrayProcessor::class, $prototypeFinisherDefinition['FormEngine']['elements'])->forEach(
232  GeneralUtility::makeInstance(
233  ArrayProcessing::class,
234  'convertToFlexFormSheets',
235  '^(.*)\.config\.type$',
236  GeneralUtility::makeInstance(FinisherOptionGenerator::class, $converterDto)
237  )
238  );
239 
240  $sheet[$sheetIdentifier]['ROOT']['el'] = $converterDto->getResult();
241  ‪ArrayUtility::mergeRecursiveWithOverrule($sheets['sheets'], $sheet);
242  }
243  if (empty($sheets['sheets'])) {
244  return [];
245  }
246 
247  return $sheets;
248  }
249 
258  protected function ‪initializeNewSheetArray(string $sheetIdentifier, string $finisherName): array
259  {
260  if (empty($sheetIdentifier)) {
261  throw new \InvalidArgumentException('$sheetIdentifier must not be empty.', 1472060918);
262  }
263  if (empty($finisherName)) {
264  throw new \InvalidArgumentException('$finisherName must not be empty.', 1472060919);
265  }
266 
267  return [
268  $sheetIdentifier => [
269  'ROOT' => [
270  'TCEforms' => [
271  'sheetTitle' => $finisherName,
272  ],
273  'type' => 'array',
274  'el' => [],
275  ],
276  ],
277  ];
278  }
279 
285  protected function ‪addSelectedPersistenceIdentifier(string $persistenceIdentifier, array $dataStructure): array
286  {
287  if (!empty($persistenceIdentifier)) {
288  $dataStructure['sheets']['sDEF']['ROOT']['el']['settings.persistenceIdentifier']['TCEforms']['config']['items'][] = [
289  sprintf(
290  $this->‪getLanguageService()->sL(self::L10N_PREFIX . 'tt_content.preview.inaccessiblePersistenceIdentifier'),
291  $persistenceIdentifier
292  ),
293  $persistenceIdentifier,
294  ];
295  }
296 
297  return $dataStructure;
298  }
299 
304  {
305  $messageText = sprintf(
306  $this->‪getLanguageService()->sL(self::L10N_PREFIX . 'tt_content.preview.invalidFrameworkConfiguration.text'),
307  $e->getMessage()
308  );
309 
310  GeneralUtility::makeInstance(ObjectManager::class)
311  ->get(FlashMessageService::class)
312  ->getMessageQueueByIdentifier('core.template.flashMessages')
313  ->enqueue(
314  GeneralUtility::makeInstance(
315  FlashMessage::class,
316  $messageText,
317  $this->‪getLanguageService()->sL(self::L10N_PREFIX . 'tt_content.preview.invalidFrameworkConfiguration.title'),
319  true
320  )
321  );
322  }
323 
332  string $persistenceIdentifier,
333  string $prototypeName,
334  string $formIdentifier,
335  string $finisherIdentifier
336  ): string {
337  return md5(
338  implode('', [
339  $persistenceIdentifier,
340  $prototypeName,
341  $formIdentifier,
342  $finisherIdentifier
343  ])
344  );
345  }
346 
354  string $finisherIdentifier,
355  array $finishersDefinition,
356  array $prototypeConfiguration
357  ): array {
358  if (isset($finishersDefinition[$finisherIdentifier]['FormEngine']['translationFile'])) {
359  $translationFile = $finishersDefinition[$finisherIdentifier]['FormEngine']['translationFile'];
360  } else {
361  $translationFile = $prototypeConfiguration['formEngine']['translationFile'];
362  }
363 
364  $finishersDefinition[$finisherIdentifier]['FormEngine'] = ‪TranslationService::getInstance()->‪translateValuesRecursive(
365  $finishersDefinition[$finisherIdentifier]['FormEngine'],
366  $translationFile
367  );
368 
369  return $finishersDefinition;
370  }
371 
376  {
377  return ‪$GLOBALS['LANG'];
378  }
379 }
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\initializeNewSheetArray
‪array initializeNewSheetArray(string $sheetIdentifier, string $finisherName)
Definition: DataStructureIdentifierHook.php:258
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook
Definition: DataStructureIdentifierHook.php:45
‪TYPO3\CMS\Form\Service\TranslationService\getInstance
‪static TranslationService getInstance()
Definition: TranslationService.php:82
‪TYPO3\CMS\Core\Messaging\AbstractMessage
Definition: AbstractMessage.php:24
‪TYPO3\CMS\Form\Service\TranslationService
Definition: TranslationService.php:43
‪TYPO3\CMS\Form\Service\TranslationService\translateValuesRecursive
‪array translateValuesRecursive(array $array, $translationFile=null)
Definition: TranslationService.php:178
‪TYPO3\CMS\Form\Domain\Configuration\FlexformConfiguration\Processors\ProcessorDto
Definition: ProcessorDto.php:24
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\translateFinisherDefinitionByIdentifier
‪array translateFinisherDefinitionByIdentifier(string $finisherIdentifier, array $finishersDefinition, array $prototypeConfiguration)
Definition: DataStructureIdentifierHook.php:353
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\buildFlexformSheetIdentifier
‪string buildFlexformSheetIdentifier(string $persistenceIdentifier, string $prototypeName, string $formIdentifier, string $finisherIdentifier)
Definition: DataStructureIdentifierHook.php:331
‪TYPO3\CMS\Core\Utility\ArrayUtility\mergeRecursiveWithOverrule
‪static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
Definition: ArrayUtility.php:614
‪TYPO3\CMS\Form\Domain\Configuration\ArrayProcessing\ArrayProcessing
Definition: ArrayProcessing.php:25
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\parseDataStructureByIdentifierPostProcess
‪array parseDataStructureByIdentifierPostProcess(array $dataStructure, array $identifier)
Definition: DataStructureIdentifierHook.php:105
‪TYPO3\CMS\Form\Hooks
Definition: DataStructureIdentifierHook.php:3
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\addSelectedPersistenceIdentifier
‪array addSelectedPersistenceIdentifier(string $persistenceIdentifier, array $dataStructure)
Definition: DataStructureIdentifierHook.php:285
‪TYPO3\CMS\Form\Domain\Configuration\ArrayProcessing\ArrayProcessor
Definition: ArrayProcessor.php:28
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\addInvalidFrameworkConfigurationFlashMessage
‪addInvalidFrameworkConfigurationFlashMessage(\Exception $e)
Definition: DataStructureIdentifierHook.php:303
‪TYPO3\CMS\Form\Domain\Configuration\FlexformConfiguration\Processors\FinisherOptionGenerator
Definition: FinisherOptionGenerator.php:29
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\getAdditionalFinisherSheets
‪array getAdditionalFinisherSheets(string $persistenceIdentifier, array $formDefinition)
Definition: DataStructureIdentifierHook.php:181
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\getLanguageService
‪LanguageService getLanguageService()
Definition: DataStructureIdentifierHook.php:375
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\L10N_PREFIX
‪const L10N_PREFIX
Definition: DataStructureIdentifierHook.php:50
‪TYPO3\CMS\Form\Domain\Configuration\ConfigurationService
Definition: ConfigurationService.php:49
‪TYPO3\CMS\Form\Mvc\Configuration\Exception\ParseErrorException
Definition: ParseErrorException.php:24
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:22
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Form\Hooks\DataStructureIdentifierHook\getDataStructureIdentifierPostProcess
‪array getDataStructureIdentifierPostProcess(array $fieldTca, string $tableName, string $fieldName, array $row, array $identifier)
Definition: DataStructureIdentifierHook.php:64
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface
Definition: FormPersistenceManagerInterface.php:28
‪TYPO3\CMS\Extbase\Object\ObjectManager
Definition: ObjectManager.php:25
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:25
‪TYPO3\CMS\Core\Messaging\AbstractMessage\ERROR
‪const ERROR
Definition: AbstractMessage.php:29
‪TYPO3\CMS\Form\Mvc\Configuration\Exception\NoSuchFileException
Definition: NoSuchFileException.php:24