‪TYPO3CMS  10.4
FormPersistenceManager.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
18 /*
19  * Inspired by and partially taken from the Neos.Form package (www.neos.io)
20  */
21 
23 
47 
54 {
55  const ‪FORM_DEFINITION_FILE_EXTENSION = '.form.yaml';
56 
60  protected ‪$yamlSource;
61 
65  protected ‪$storageRepository;
66 
70  protected ‪$formSettings;
71 
76 
80  protected ‪$runtimeCache;
81 
86 
92  {
93  $this->yamlSource = ‪$yamlSource;
94  }
95 
101  {
102  $this->storageRepository = ‪$storageRepository;
103  }
104 
109  {
110  $this->filePersistenceSlot = ‪$filePersistenceSlot;
111  }
112 
117  {
118  $this->resourceFactory = ‪$resourceFactory;
119  }
120 
124  public function ‪initializeObject()
125  {
126  $this->formSettings = GeneralUtility::makeInstance(ObjectManager::class)
127  ->get(ConfigurationManagerInterface::class)
129  $this->runtimeCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('runtime');
130  }
131 
140  public function ‪load(string $persistenceIdentifier): array
141  {
142  $cacheKey = 'formLoad' . md5($persistenceIdentifier);
143 
144  $yaml = $this->runtimeCache->get($cacheKey);
145  if ($yaml !== false) {
146  return $yaml;
147  }
148 
149  $file = $this->‪retrieveFileByPersistenceIdentifier($persistenceIdentifier);
150 
151  try {
152  $yaml = $this->yamlSource->load([$file]);
153  $this->‪generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension($yaml, $persistenceIdentifier);
154  } catch (\Exception $e) {
155  $yaml = [
156  'type' => 'Form',
157  'identifier' => $persistenceIdentifier,
158  'label' => $e->getMessage(),
159  'invalid' => true,
160  ];
161  }
162  $this->runtimeCache->set($cacheKey, $yaml);
163 
164  return $yaml;
165  }
166 
180  public function ‪save(string $persistenceIdentifier, array $formDefinition)
181  {
182  if (!$this->‪hasValidFileExtension($persistenceIdentifier)) {
183  throw new PersistenceManagerException(sprintf('The file "%s" could not be saved.', $persistenceIdentifier), 1477679820);
184  }
185 
186  if ($this->‪pathIsIntendedAsExtensionPath($persistenceIdentifier)) {
187  if (!$this->formSettings['persistenceManager']['allowSaveToExtensionPaths']) {
188  throw new PersistenceManagerException('Save to extension paths is not allowed.', 1477680881);
189  }
190  if (!$this->‪isFileWithinAccessibleExtensionFolders($persistenceIdentifier)) {
191  $message = sprintf('The file "%s" could not be saved. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $persistenceIdentifier);
192  throw new PersistenceManagerException($message, 1484073571);
193  }
194  $fileToSave = GeneralUtility::getFileAbsFileName($persistenceIdentifier);
195  } else {
196  $fileToSave = $this->‪getOrCreateFile($persistenceIdentifier);
197  }
198 
199  try {
200  $this->yamlSource->save($fileToSave, $formDefinition);
201  } catch (FileWriteException $e) {
202  throw new PersistenceManagerException(sprintf(
203  'The file "%s" could not be saved: %s',
204  $persistenceIdentifier,
205  $e->getMessage()
206  ), 1512582637, $e);
207  }
208  }
209 
218  public function delete(string $persistenceIdentifier)
219  {
220  if (!$this->‪hasValidFileExtension($persistenceIdentifier)) {
221  throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239534);
222  }
223  if (!$this->‪exists($persistenceIdentifier)) {
224  throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239535);
225  }
226  if ($this->‪pathIsIntendedAsExtensionPath($persistenceIdentifier)) {
227  if (!$this->formSettings['persistenceManager']['allowDeleteFromExtensionPaths']) {
228  throw new PersistenceManagerException(sprintf('The file "%s" could not be removed.', $persistenceIdentifier), 1472239536);
229  }
230  if (!$this->‪isFileWithinAccessibleExtensionFolders($persistenceIdentifier)) {
231  $message = sprintf('The file "%s" could not be removed. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $persistenceIdentifier);
232  throw new PersistenceManagerException($message, 1484073878);
233  }
234  $fileToDelete = GeneralUtility::getFileAbsFileName($persistenceIdentifier);
235  unlink($fileToDelete);
236  } else {
237  [$storageUid, $fileIdentifier] = explode(':', $persistenceIdentifier, 2);
238  $storage = $this->‪getStorageByUid((int)$storageUid);
239  $file = $storage->getFile($fileIdentifier);
240  if (!$storage->checkFileActionPermission('delete', $file)) {
241  throw new PersistenceManagerException(sprintf('No delete access to file "%s".', $persistenceIdentifier), 1472239516);
242  }
243  $storage->deleteFile($file);
244  }
245  }
246 
254  public function ‪exists(string $persistenceIdentifier): bool
255  {
256  $exists = false;
257  if ($this->‪hasValidFileExtension($persistenceIdentifier)) {
258  if ($this->‪pathIsIntendedAsExtensionPath($persistenceIdentifier)) {
259  if ($this->‪isFileWithinAccessibleExtensionFolders($persistenceIdentifier)) {
260  $exists = file_exists(GeneralUtility::getFileAbsFileName($persistenceIdentifier));
261  }
262  } else {
263  [$storageUid, $fileIdentifier] = explode(':', $persistenceIdentifier, 2);
264  $storage = $this->‪getStorageByUid((int)$storageUid);
265  $exists = $storage->hasFile($fileIdentifier);
266  }
267  }
268  return $exists;
269  }
270 
281  public function ‪listForms(): array
282  {
283  $identifiers = [];
284  $forms = [];
285 
286  foreach ($this->‪retrieveYamlFilesFromStorageFolders() as $file) {
287  $form = $this->‪loadMetaData($file);
288 
289  if (!$this->‪looksLikeAFormDefinition($form)) {
290  continue;
291  }
292 
293  $persistenceIdentifier = $file->getCombinedIdentifier();
294  if ($this->‪hasValidFileExtension($persistenceIdentifier)) {
295  $forms[] = [
296  'identifier' => $form['identifier'],
297  'name' => $form['label'] ?? $form['identifier'],
298  'persistenceIdentifier' => $persistenceIdentifier,
299  'readOnly' => false,
300  'removable' => true,
301  'location' => 'storage',
302  'duplicateIdentifier' => false,
303  'invalid' => $form['invalid'],
304  'fileUid' => $form['fileUid'],
305  ];
306  $identifiers[$form['identifier']]++;
307  }
308  }
309 
310  foreach ($this->retrieveYamlFilesFromExtensionFolders() as $fullPath => $fileName) {
311  $form = $this->‪loadMetaData($fullPath);
312 
313  if ($this->‪looksLikeAFormDefinition($form)) {
314  if ($this->‪hasValidFileExtension($fileName)) {
315  $forms[] = [
316  'identifier' => $form['identifier'],
317  'name' => $form['label'] ?? $form['identifier'],
318  'persistenceIdentifier' => $fullPath,
319  'readOnly' => $this->formSettings['persistenceManager']['allowSaveToExtensionPaths'] ? false: true,
320  'removable' => $this->formSettings['persistenceManager']['allowDeleteFromExtensionPaths'] ? true: false,
321  'location' => 'extension',
322  'duplicateIdentifier' => false,
323  'invalid' => $form['invalid'],
324  'fileUid' => $form['fileUid'],
325  ];
326  $identifiers[$form['identifier']]++;
327  }
328  }
329  }
330 
331  foreach ($identifiers as $identifier => $count) {
332  if ($count > 1) {
333  foreach ($forms as &$formDefinition) {
334  if ($formDefinition['identifier'] === $identifier) {
335  $formDefinition['duplicateIdentifier'] = true;
336  }
337  }
338  }
339  }
340 
341  return $this->‪sortForms($forms);
342  }
343 
351  public function ‪retrieveYamlFilesFromStorageFolders(): array
352  {
353  $filesFromStorageFolders = [];
354 
355  $fileExtensionFilter = GeneralUtility::makeInstance(FileExtensionFilter::class);
356  $fileExtensionFilter->setAllowedFileExtensions(['yaml']);
357 
358  foreach ($this->‪getAccessibleFormStorageFolders() as $folder) {
359  $storage = $folder->getStorage();
360  $storage->setFileAndFolderNameFilters([
361  [$fileExtensionFilter, 'filterFileList']
362  ]);
363 
364  $files = $folder->getFiles(
365  0,
366  0,
368  true
369  );
370  $filesFromStorageFolders = array_merge($filesFromStorageFolders, array_values($files));
371  $storage->resetFileAndFolderNameFiltersToDefault();
372  }
373 
374  return $filesFromStorageFolders;
375  }
376 
384  public function retrieveYamlFilesFromExtensionFolders(): array
385  {
387 
388  foreach ($this->‪getAccessibleExtensionFolders() as $relativePath => $fullPath) {
389  foreach (new \DirectoryIterator($fullPath) as $fileInfo) {
390  if ($fileInfo->getExtension() !== 'yaml') {
391  continue;
392  }
393  ‪$filesFromExtensionFolders[$relativePath . $fileInfo->getFilename()] = $fileInfo->getFilename();
394  }
395  }
396 
398  }
399 
411  public function ‪getAccessibleFormStorageFolders(): array
412  {
413  $storageFolders = [];
414 
415  if (
416  !isset($this->formSettings['persistenceManager']['allowedFileMounts'])
417  || !is_array($this->formSettings['persistenceManager']['allowedFileMounts'])
418  || empty($this->formSettings['persistenceManager']['allowedFileMounts'])
419  ) {
420  return $storageFolders;
421  }
422 
423  foreach ($this->formSettings['persistenceManager']['allowedFileMounts'] as $allowedFileMount) {
424  $allowedFileMount = rtrim($allowedFileMount, '/') . '/';
425  // $fileMountPath is like "/form_definitions/" or "/group_homes/1/form_definitions/"
426  [$storageUid, $fileMountPath] = explode(':', $allowedFileMount, 2);
427 
428  try {
429  $storage = $this->‪getStorageByUid((int)$storageUid);
430  } catch (PersistenceManagerException $e) {
431  continue;
432  }
433 
434  $isStorageFileMount = false;
435  $parentFolder = $storage->getRootLevelFolder(false);
436 
437  foreach ($storage->getFileMounts() as $storageFileMount) {
439  $storageFileMountFolder = $storageFileMount['folder'];
440 
441  // 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.
442  if (‪StringUtility::beginsWith($fileMountPath, $storageFileMountFolder->getIdentifier())) {
443  $isStorageFileMount = true;
444  $parentFolder = $storageFileMountFolder;
445  }
446  }
447 
448  // Get storage folder object, create it if missing
449  try {
450  $fileMountFolder = $storage->getFolder($fileMountPath);
451  } catch (InsufficientFolderAccessPermissionsException $e) {
452  continue;
453  } catch (FolderDoesNotExistException $e) {
454  if ($isStorageFileMount) {
455  $fileMountPath = substr(
456  $fileMountPath,
457  strlen($parentFolder->getIdentifier())
458  );
459  }
460 
461  try {
462  $fileMountFolder = $storage->createFolder($fileMountPath, $parentFolder);
463  } catch (InsufficientFolderAccessPermissionsException $e) {
464  continue;
465  }
466  }
467 
468  $storageFolders[$allowedFileMount] = $fileMountFolder;
469  }
470  return $storageFolders;
471  }
472 
483  public function ‪getAccessibleExtensionFolders(): array
484  {
485  $extensionFolders = $this->runtimeCache->get('formAccessibleExtensionFolders');
486 
487  if ($extensionFolders !== false) {
488  return $extensionFolders;
489  }
490 
491  $extensionFolders = [];
492  if (
493  !isset($this->formSettings['persistenceManager']['allowedExtensionPaths'])
494  || !is_array($this->formSettings['persistenceManager']['allowedExtensionPaths'])
495  || empty($this->formSettings['persistenceManager']['allowedExtensionPaths'])
496  ) {
497  $this->runtimeCache->set('formAccessibleExtensionFolders', $extensionFolders);
498  return $extensionFolders;
499  }
500 
501  foreach ($this->formSettings['persistenceManager']['allowedExtensionPaths'] as $allowedExtensionPath) {
502  if (!$this->‪pathIsIntendedAsExtensionPath($allowedExtensionPath)) {
503  continue;
504  }
505 
506  $allowedExtensionFullPath = GeneralUtility::getFileAbsFileName($allowedExtensionPath);
507  if (!file_exists($allowedExtensionFullPath)) {
508  continue;
509  }
510  $allowedExtensionPath = rtrim($allowedExtensionPath, '/') . '/';
511  $extensionFolders[$allowedExtensionPath] = $allowedExtensionFullPath;
512  }
513 
514  $this->runtimeCache->set('formAccessibleExtensionFolders', $extensionFolders);
515  return $extensionFolders;
516  }
517 
529  public function ‪getUniquePersistenceIdentifier(string $formIdentifier, string $savePath): string
530  {
531  $savePath = rtrim($savePath, '/') . '/';
532  $formPersistenceIdentifier = $savePath . $formIdentifier . ‪self::FORM_DEFINITION_FILE_EXTENSION;
533  if (!$this->‪exists($formPersistenceIdentifier)) {
534  return $formPersistenceIdentifier;
535  }
536  for ($attempts = 1; $attempts < 100; $attempts++) {
537  $formPersistenceIdentifier = $savePath . sprintf('%s_%d', $formIdentifier, $attempts) . ‪self::FORM_DEFINITION_FILE_EXTENSION;
538  if (!$this->‪exists($formPersistenceIdentifier)) {
539  return $formPersistenceIdentifier;
540  }
541  }
542  $formPersistenceIdentifier = $savePath . sprintf('%s_%d', $formIdentifier, time()) . ‪self::FORM_DEFINITION_FILE_EXTENSION;
543  if (!$this->‪exists($formPersistenceIdentifier)) {
544  return $formPersistenceIdentifier;
545  }
546 
547  throw new NoUniquePersistenceIdentifierException(
548  sprintf('Could not find a unique persistence identifier for form identifier "%s" after %d attempts', $formIdentifier, $attempts),
549  1476010403
550  );
551  }
552 
563  public function ‪getUniqueIdentifier(string $identifier): string
564  {
565  $originalIdentifier = $identifier;
566  if ($this->‪checkForDuplicateIdentifier($identifier)) {
567  for ($attempts = 1; $attempts < 100; $attempts++) {
568  $identifier = sprintf('%s_%d', $originalIdentifier, $attempts);
569  if (!$this->‪checkForDuplicateIdentifier($identifier)) {
570  return $identifier;
571  }
572  }
573  $identifier = $originalIdentifier . '_' . time();
574  if ($this->‪checkForDuplicateIdentifier($identifier)) {
575  throw new NoUniqueIdentifierException(
576  sprintf('Could not find a unique identifier for form identifier "%s" after %d attempts', $identifier, $attempts),
577  1477688567
578  );
579  }
580  }
581  return $identifier;
582  }
583 
591  public function ‪checkForDuplicateIdentifier(string $identifier): bool
592  {
593  $identifierUsed = false;
594  foreach ($this->‪listForms() as $formDefinition) {
595  if ($formDefinition['identifier'] === $identifier) {
596  $identifierUsed = true;
597  break;
598  }
599  }
600  return $identifierUsed;
601  }
602 
614  public function ‪isAllowedPersistencePath(string $persistencePath): bool
615  {
616  $pathinfo = ‪PathUtility::pathinfo($persistencePath);
617  $persistencePathIsFile = isset($pathinfo['extension']);
618 
619  if (
620  $persistencePathIsFile
621  && $this->‪pathIsIntendedAsExtensionPath($persistencePath)
622  && $this->‪hasValidFileExtension($persistencePath)
623  && $this->‪isFileWithinAccessibleExtensionFolders($persistencePath)
624  ) {
625  return true;
626  }
627  if (
628  $persistencePathIsFile
629  && $this->‪pathIsIntendedAsFileMountPath($persistencePath)
630  && $this->‪hasValidFileExtension($persistencePath)
631  && $this->‪isFileWithinAccessibleFormStorageFolders($persistencePath)
632  ) {
633  return true;
634  }
635  if (
636  !$persistencePathIsFile
637  && $this->‪pathIsIntendedAsExtensionPath($persistencePath)
638  && $this->‪isAccessibleExtensionFolder($persistencePath)
639  ) {
640  return true;
641  }
642  if (
643  !$persistencePathIsFile
644  && $this->‪pathIsIntendedAsFileMountPath($persistencePath)
645  && $this->‪isAccessibleFormStorageFolder($persistencePath)
646  ) {
647  return true;
648  }
649 
650  return false;
651  }
652 
657  protected function ‪pathIsIntendedAsExtensionPath(string $path): bool
658  {
659  return strpos($path, 'EXT:') === 0;
660  }
661 
666  protected function ‪pathIsIntendedAsFileMountPath(string $path): bool
667  {
668  if (empty($path)) {
669  return false;
670  }
671 
672  [$storageUid, $pathIdentifier] = explode(':', $path, 2);
673  if (empty($storageUid) || empty($pathIdentifier)) {
674  return false;
675  }
676 
677  return ‪MathUtility::canBeInterpretedAsInteger($storageUid);
678  }
679 
689  protected function ‪getOrCreateFile(string $persistenceIdentifier): File
690  {
691  [$storageUid, $fileIdentifier] = explode(':', $persistenceIdentifier, 2);
692  $storage = $this->‪getStorageByUid((int)$storageUid);
693  $pathinfo = ‪PathUtility::pathinfo($fileIdentifier);
694 
695  if (!$storage->hasFolder($pathinfo['dirname'])) {
696  throw new PersistenceManagerException(sprintf('Could not create folder "%s".', $pathinfo['dirname']), 1471630579);
697  }
698 
699  try {
700  $folder = $storage->getFolder($pathinfo['dirname']);
701  } catch (InsufficientFolderAccessPermissionsException $e) {
702  throw new PersistenceManagerException(sprintf('No read access to folder "%s".', $pathinfo['dirname']), 1512583307);
703  }
704 
705  if (!$storage->checkFolderActionPermission('write', $folder)) {
706  throw new PersistenceManagerException(sprintf('No write access to folder "%s".', $pathinfo['dirname']), 1471630580);
707  }
708 
709  if (!$storage->hasFile($fileIdentifier)) {
710  $this->filePersistenceSlot->allowInvocation(
712  $folder->getCombinedIdentifier() . $pathinfo['basename']
713  );
714  $file = $folder->createFile($pathinfo['basename']);
715  } else {
716  $file = $storage->getFile($fileIdentifier);
717  }
718  return $file;
719  }
720 
728  protected function ‪getStorageByUid(int $storageUid): ResourceStorage
729  {
730  $storage = $this->storageRepository->findByUid($storageUid);
731  if (
732  !$storage instanceof ResourceStorage
733  || !$storage->isBrowsable()
734  ) {
735  throw new PersistenceManagerException(sprintf('Could not access storage with uid "%d".', $storageUid), 1471630581);
736  }
737  return $storage;
738  }
739 
745  protected function ‪loadMetaData($persistenceIdentifier): array
746  {
747  if ($persistenceIdentifier instanceof ‪File) {
748  $file = $persistenceIdentifier;
749  $persistenceIdentifier = $file->getCombinedIdentifier();
750  } else {
751  $file = $this->‪retrieveFileByPersistenceIdentifier($persistenceIdentifier);
752  }
753 
754  try {
755  $rawYamlContent = $file->getContents();
756 
757  if ($rawYamlContent === false) {
758  throw new ‪NoSuchFileException(sprintf('YAML file "%s" could not be loaded', $persistenceIdentifier), 1524684462);
759  }
760 
761  $yaml = $this->‪extractMetaDataFromCouldBeFormDefinition($rawYamlContent);
762  $this->‪generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension($yaml, $persistenceIdentifier);
763  $yaml['fileUid'] = $file->getUid();
764  } catch (\‪Exception $e) {
765  $yaml = [
766  'type' => 'Form',
767  'identifier' => $persistenceIdentifier,
768  'label' => $e->getMessage(),
769  'invalid' => true,
770  ];
771  }
772 
773  return $yaml;
774  }
775 
780  protected function ‪extractMetaDataFromCouldBeFormDefinition(string $maybeRawFormDefinition): array
781  {
782  $metaDataProperties = ['identifier', 'type', 'label', 'prototypeName'];
783  $metaData = [];
784  foreach (explode(LF, $maybeRawFormDefinition) as $line) {
785  if (empty($line) || $line[0] === ' ') {
786  continue;
787  }
788 
789  [$key, $value] = explode(':', $line);
790  if (
791  empty($key)
792  || empty($value)
793  || !in_array($key, $metaDataProperties, true)
794  ) {
795  continue;
796  }
797 
798  $value = trim($value, " '\"\r");
799  $metaData[$key] = $value;
800  }
801 
802  return $metaData;
803  }
804 
810  protected function ‪generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension(array $formDefinition, string $persistenceIdentifier): void
811  {
812  if (
813  $this->‪looksLikeAFormDefinition($formDefinition)
814  && !$this->‪hasValidFileExtension($persistenceIdentifier)
815  ) {
816  throw new ‪PersistenceManagerException(sprintf('Form definition "%s" does not end with ".form.yaml".', $persistenceIdentifier), 1531160649);
817  }
818  }
819 
826  protected function ‪retrieveFileByPersistenceIdentifier(string $persistenceIdentifier): ‪File
827  {
828  if (pathinfo($persistenceIdentifier, PATHINFO_EXTENSION) !== 'yaml') {
829  throw new ‪PersistenceManagerException(sprintf('The file "%s" could not be loaded.', $persistenceIdentifier), 1477679819);
830  }
831 
832  if (
833  $this->‪pathIsIntendedAsExtensionPath($persistenceIdentifier)
834  && !$this->‪isFileWithinAccessibleExtensionFolders($persistenceIdentifier)
835  ) {
836  $message = sprintf('The file "%s" could not be loaded. Please check your configuration option "persistenceManager.allowedExtensionPaths"', $persistenceIdentifier);
837  throw new PersistenceManagerException($message, 1484071985);
838  }
839 
840  try {
841  $file = $this->resourceFactory->retrieveFileOrFolderObject($persistenceIdentifier);
842  } catch (\Exception $e) {
843  // Top level catch to ensure useful following exception handling, because FAL throws top level exceptions.
844  $file = null;
845  }
846 
847  if ($file === null) {
848  throw new NoSuchFileException(sprintf('YAML file "%s" could not be loaded', $persistenceIdentifier), 1524684442);
849  }
850 
851  if (!$file->getStorage()->checkFileActionPermission('read', $file)) {
852  throw new PersistenceManagerException(sprintf('No read access to file "%s".', $persistenceIdentifier), 1471630578);
853  }
854 
855  return $file;
856  }
857 
862  protected function ‪hasValidFileExtension(string $fileName): bool
863  {
864  return ‪StringUtility::endsWith($fileName, self::FORM_DEFINITION_FILE_EXTENSION);
865  }
866 
871  protected function ‪isFileWithinAccessibleExtensionFolders(string $fileName): bool
872  {
873  $pathInfo = ‪PathUtility::pathinfo($fileName, PATHINFO_DIRNAME);
874  $pathInfo = is_string($pathInfo) ? $pathInfo : '';
875  $dirName = rtrim($pathInfo, '/') . '/';
876  return array_key_exists($dirName, $this->‪getAccessibleExtensionFolders());
877  }
878 
883  protected function ‪isFileWithinAccessibleFormStorageFolders(string $fileName): bool
884  {
885  $pathInfo = ‪PathUtility::pathinfo($fileName, PATHINFO_DIRNAME);
886  $pathInfo = is_string($pathInfo) ? $pathInfo : '';
887  $dirName = rtrim($pathInfo, '/') . '/';
888  return array_key_exists($dirName, $this->‪getAccessibleFormStorageFolders());
889  }
890 
895  protected function ‪isAccessibleExtensionFolder(string $folderName): bool
896  {
897  $folderName = rtrim($folderName, '/') . '/';
898  return array_key_exists($folderName, $this->‪getAccessibleExtensionFolders());
899  }
900 
905  protected function ‪isAccessibleFormStorageFolder(string $folderName): bool
906  {
907  $folderName = rtrim($folderName, '/') . '/';
908  return array_key_exists($folderName, $this->‪getAccessibleFormStorageFolders());
909  }
910 
915  protected function ‪looksLikeAFormDefinition(array $data): bool
916  {
917  return isset($data['identifier'], $data['type']) && !empty($data['identifier']) && trim($data['type']) === 'Form';
918  }
919 
924  protected function ‪sortForms(array $forms): array
925  {
926  $keys = $this->formSettings['persistenceManager']['sortByKeys'] ?? ['name', 'fileUid'];
927  $ascending = $this->formSettings['persistenceManager']['sortAscending'] ?? true;
928 
929  usort($forms, function (array $a, array $b) use ($keys) {
930  foreach ($keys as $key) {
931  if (isset($a[$key]) && isset($b[$key])) {
932  $diff = strcasecmp((string)$a[$key], (string)$b[$key]);
933  if ($diff) {
934  return $diff;
935  }
936  }
937  }
938  });
939 
940  return ($ascending) ? $forms : array_reverse($forms);
941  }
942 }
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\listForms
‪array listForms()
Definition: FormPersistenceManager.php:275
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\isAccessibleFormStorageFolder
‪bool isAccessibleFormStorageFolder(string $folderName)
Definition: FormPersistenceManager.php:899
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\hasValidFileExtension
‪bool hasValidFileExtension(string $fileName)
Definition: FormPersistenceManager.php:856
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:24
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$filePersistenceSlot
‪FilePersistenceSlot $filePersistenceSlot
Definition: FormPersistenceManager.php:71
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\isFileWithinAccessibleExtensionFolders
‪bool isFileWithinAccessibleExtensionFolders(string $fileName)
Definition: FormPersistenceManager.php:865
‪TYPO3\CMS\Form\Mvc\Configuration\Exception\FileWriteException
Definition: FileWriteException.php:25
‪TYPO3\CMS\Core\Utility\StringUtility\endsWith
‪static bool endsWith($haystack, $needle)
Definition: StringUtility.php:61
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\sortForms
‪array sortForms(array $forms)
Definition: FormPersistenceManager.php:918
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$yamlSource
‪TYPO3 CMS Form Mvc Configuration YamlSource $yamlSource
Definition: FormPersistenceManager.php:59
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\checkForDuplicateIdentifier
‪bool checkForDuplicateIdentifier(string $identifier)
Definition: FormPersistenceManager.php:585
‪TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException
Definition: InsufficientFolderAccessPermissionsException.php:24
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\injectResourceFactory
‪injectResourceFactory(ResourceFactory $resourceFactory)
Definition: FormPersistenceManager.php:110
‪TYPO3\CMS\Form\Mvc\Persistence\Exception\PersistenceManagerException
Definition: PersistenceManagerException.php:28
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\isFileWithinAccessibleFormStorageFolders
‪bool isFileWithinAccessibleFormStorageFolders(string $fileName)
Definition: FormPersistenceManager.php:877
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\retrieveFileByPersistenceIdentifier
‪File retrieveFileByPersistenceIdentifier(string $persistenceIdentifier)
Definition: FormPersistenceManager.php:820
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\injectStorageRepository
‪injectStorageRepository(StorageRepository $storageRepository)
Definition: FormPersistenceManager.php:94
‪TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniqueIdentifierException
Definition: NoUniqueIdentifierException.php:26
‪TYPO3\CMS\Core\Resource\Folder\FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS
‪const FILTER_MODE_USE_OWN_AND_STORAGE_FILTERS
Definition: Folder.php:69
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getStorageByUid
‪ResourceStorage getStorageByUid(int $storageUid)
Definition: FormPersistenceManager.php:722
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\pathIsIntendedAsExtensionPath
‪bool pathIsIntendedAsExtensionPath(string $path)
Definition: FormPersistenceManager.php:651
‪TYPO3\CMS\Core\Utility\StringUtility\beginsWith
‪static bool beginsWith($haystack, $needle)
Definition: StringUtility.php:32
‪TYPO3\CMS\Form\Mvc\Persistence
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\isAllowedPersistencePath
‪bool isAllowedPersistencePath(string $persistencePath)
Definition: FormPersistenceManager.php:608
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\initializeObject
‪initializeObject()
Definition: FormPersistenceManager.php:118
‪TYPO3\CMS\Form\Slot\FilePersistenceSlot\COMMAND_FILE_CREATE
‪const COMMAND_FILE_CREATE
Definition: FilePersistenceSlot.php:40
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$formSettings
‪array $formSettings
Definition: FormPersistenceManager.php:67
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\looksLikeAFormDefinition
‪bool looksLikeAFormDefinition(array $data)
Definition: FormPersistenceManager.php:909
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getAccessibleFormStorageFolders
‪Folder[] getAccessibleFormStorageFolders()
Definition: FormPersistenceManager.php:405
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager
Definition: FormPersistenceManager.php:54
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\load
‪array load(string $persistenceIdentifier)
Definition: FormPersistenceManager.php:134
‪TYPO3\CMS\Core\Resource\ResourceStorage\isBrowsable
‪bool isBrowsable()
Definition: ResourceStorage.php:393
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:37
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:41
‪TYPO3\CMS\Core\Resource\Exception\FolderDoesNotExistException
Definition: FolderDoesNotExistException.php:22
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\exists
‪bool exists(string $persistenceIdentifier)
Definition: FormPersistenceManager.php:248
‪TYPO3\CMS\Core\Resource\StorageRepository
Definition: StorageRepository.php:31
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:24
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:35
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\extractMetaDataFromCouldBeFormDefinition
‪array extractMetaDataFromCouldBeFormDefinition(string $maybeRawFormDefinition)
Definition: FormPersistenceManager.php:774
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter
Definition: FileExtensionFilter.php:28
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getUniquePersistenceIdentifier
‪string getUniquePersistenceIdentifier(string $formIdentifier, string $savePath)
Definition: FormPersistenceManager.php:523
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$storageRepository
‪TYPO3 CMS Core Resource StorageRepository $storageRepository
Definition: FormPersistenceManager.php:63
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$filesFromExtensionFolders
‪return $filesFromExtensionFolders
Definition: FormPersistenceManager.php:391
‪TYPO3\CMS\Core\Utility\PathUtility\pathinfo
‪static string string[] pathinfo($path, $options=null)
Definition: PathUtility.php:208
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$runtimeCache
‪FrontendInterface $runtimeCache
Definition: FormPersistenceManager.php:75
‪TYPO3\CMS\Form\Slot\FilePersistenceSlot
Definition: FilePersistenceSlot.php:38
‪TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
Definition: FrontendInterface.php:22
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\injectYamlSource
‪injectYamlSource(YamlSource $yamlSource)
Definition: FormPersistenceManager.php:85
‪TYPO3\CMS\Form\Mvc\Configuration\YamlSource
Definition: YamlSource.php:44
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:122
‪TYPO3\CMS\Form\Mvc\Persistence\Exception
Definition: Exception.php:28
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getAccessibleExtensionFolders
‪array getAccessibleExtensionFolders()
Definition: FormPersistenceManager.php:477
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getOrCreateFile
‪File getOrCreateFile(string $persistenceIdentifier)
Definition: FormPersistenceManager.php:683
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\getUniqueIdentifier
‪string getUniqueIdentifier(string $identifier)
Definition: FormPersistenceManager.php:557
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\save
‪save(string $persistenceIdentifier, array $formDefinition)
Definition: FormPersistenceManager.php:174
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\injectFilePersistenceSlot
‪injectFilePersistenceSlot(FilePersistenceSlot $filePersistenceSlot)
Definition: FormPersistenceManager.php:102
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\loadMetaData
‪array loadMetaData($persistenceIdentifier)
Definition: FormPersistenceManager.php:739
‪TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface\CONFIGURATION_TYPE_YAML_SETTINGS
‪const CONFIGURATION_TYPE_YAML_SETTINGS
Definition: ConfigurationManagerInterface.php:30
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\$resourceFactory
‪ResourceFactory $resourceFactory
Definition: FormPersistenceManager.php:79
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension
‪generateErrorsIfFormDefinitionIsValidButHasInvalidFileExtension(array $formDefinition, string $persistenceIdentifier)
Definition: FormPersistenceManager.php:804
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\isAccessibleExtensionFolder
‪bool isAccessibleExtensionFolder(string $folderName)
Definition: FormPersistenceManager.php:889
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManagerInterface
Definition: FormPersistenceManagerInterface.php:32
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:22
‪TYPO3\CMS\Extbase\Object\ObjectManager
Definition: ObjectManager.php:28
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\pathIsIntendedAsFileMountPath
‪bool pathIsIntendedAsFileMountPath(string $path)
Definition: FormPersistenceManager.php:660
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\FORM_DEFINITION_FILE_EXTENSION
‪const FORM_DEFINITION_FILE_EXTENSION
Definition: FormPersistenceManager.php:55
‪TYPO3\CMS\Form\Mvc\Configuration\Exception\NoSuchFileException
Definition: NoSuchFileException.php:25
‪TYPO3\CMS\Form\Mvc\Persistence\Exception\NoUniquePersistenceIdentifierException
Definition: NoUniquePersistenceIdentifierException.php:26
‪TYPO3\CMS\Form\Mvc\Persistence\FormPersistenceManager\retrieveYamlFilesFromStorageFolders
‪File[] retrieveYamlFilesFromStorageFolders()
Definition: FormPersistenceManager.php:345
‪TYPO3\CMS\Form\Mvc\Configuration\ConfigurationManagerInterface
Definition: ConfigurationManagerInterface.php:29