‪TYPO3CMS  ‪main
FilesControlContainer.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
23 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Core\Imaging\IconSize;
35 
48 {
49  public const ‪NODE_TYPE_IDENTIFIER = 'file';
50 
51  private const ‪FILE_REFERENCE_TABLE = 'sys_file_reference';
52 
56  protected array ‪$fileReferenceData = [];
57 
61  protected array ‪$javaScriptModules = [];
62 
64  'tcaDescription' => [
65  'renderType' => 'tcaDescription',
66  ],
67  ];
68 
69  protected ‪$defaultFieldWizard = [
70  'localizationStateSelector' => [
71  'renderType' => 'localizationStateSelector',
72  ],
73  ];
74 
75  public function ‪__construct(
76  private readonly ‪IconFactory $iconFactory,
77  private readonly ‪InlineStackProcessor $inlineStackProcessor,
78  private readonly EventDispatcherInterface $eventDispatcher,
79  private readonly ‪OnlineMediaHelperRegistry $onlineMediaHelperRegistry,
80  private readonly ‪DefaultUploadFolderResolver $defaultUploadFolderResolver,
81  ) {}
82 
88  public function ‪render(): array
89  {
90  $languageService = $this->‪getLanguageService();
91 
92  $this->fileReferenceData = $this->data['inlineData'];
93 
94  $this->inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
95 
96  $table = $this->data['tableName'];
97  $row = $this->data['databaseRow'];
98  $field = $this->data['fieldName'];
99  $parameterArray = $this->data['parameterArray'];
100 
101  $resultArray = $this->‪initializeResultArray();
102 
103  $config = $parameterArray['fieldConf']['config'];
104  $isReadOnly = (bool)($config['readOnly'] ?? false);
105  $language = 0;
106  if (BackendUtility::isTableLocalizable($table)) {
107  $languageFieldName = ‪$GLOBALS['TCA'][$table]['ctrl']['languageField'] ?? '';
108  $language = isset($row[$languageFieldName][0]) ? (int)$row[$languageFieldName][0] : (int)$row[$languageFieldName];
109  }
110 
111  // Add the current inline job to the structure stack
112  $newStructureItem = [
113  'table' => $table,
114  'uid' => $row['uid'],
115  'field' => $field,
116  'config' => $config,
117  ];
118 
119  // Extract FlexForm parts (if any) from element name, e.g. array('vDEF', 'lDEF', 'FlexField', 'vDEF')
120  $itemName = (string)$parameterArray['itemFormElName'];
121  if ($itemName !== '') {
122  $flexFormParts = $this->‪extractFlexFormParts($itemName);
123  if ($flexFormParts !== null) {
124  $newStructureItem['flexform'] = $flexFormParts;
125  if ($flexFormParts !== []
126  && isset($this->data['processedTca']['columns'][$field]['config']['dataStructureIdentifier'])
127  ) {
128  // Transport the flexform DS identifier fields to the FormFilesAjaxController
129  $config['dataStructureIdentifier'] = $this->data['processedTca']['columns'][$field]['config']['dataStructureIdentifier'];
130  }
131  }
132  }
133 
134  $this->inlineStackProcessor->pushStableStructureItem($newStructureItem);
135 
136  // Hand over original returnUrl to FormFilesAjaxController. Needed if opening for instance a
137  // nested element in a new view to then go back to the original returnUrl and not the url of
138  // the inline ajax controller
139  $config['originalReturnUrl'] = $this->data['returnUrl'];
140 
141  // e.g. data[<table>][<uid>][<field>]
142  $formFieldName = $this->inlineStackProcessor->getCurrentStructureFormPrefix();
143  // e.g. data-<pid>-<table1>-<uid1>-<field1>-<table2>-<uid2>-<field2>
144  $formFieldIdentifier = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
145 
146  $config['inline']['first'] = false;
147 
148  $firstChild = reset($this->data['parameterArray']['fieldConf']['children']);
149  if (isset($firstChild['databaseRow']['uid'])) {
150  $config['inline']['first'] = $firstChild['databaseRow']['uid'];
151  }
152  $config['inline']['last'] = false;
153  $lastChild = end($this->data['parameterArray']['fieldConf']['children']);
154  if (isset($lastChild['databaseRow']['uid'])) {
155  $config['inline']['last'] = $lastChild['databaseRow']['uid'];
156  }
157 
158  $top = $this->inlineStackProcessor->getStructureLevel(0);
159 
160  $this->fileReferenceData['config'][$formFieldIdentifier] = [
162  ];
163  $configJson = (string)json_encode($config);
164  $this->fileReferenceData['config'][$formFieldIdentifier . '-' . ‪self::FILE_REFERENCE_TABLE] = [
165  'min' => $config['minitems'],
166  'max' => $config['maxitems'],
167  'sortable' => $config['appearance']['useSortable'] ?? false,
168  'top' => [
169  'table' => $top['table'],
170  'uid' => $top['uid'],
171  ],
172  'context' => [
173  'config' => $configJson,
174  'hmac' => ‪GeneralUtility::hmac($configJson, 'FilesContext'),
175  ],
176  ];
177  $this->fileReferenceData['nested'][$formFieldIdentifier] = $this->data['tabAndInlineStack'];
178 
179  $resultArray['inlineData'] = ‪$this->fileReferenceData;
180 
181  // @todo: It might be a good idea to have something like "isLocalizedRecord" or similar set by a data provider
182  $uidOfDefaultRecord = $row[‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null] ?? 0;
183  $isLocalizedParent = $language > 0
184  && ($uidOfDefaultRecord[0] ?? $uidOfDefaultRecord) > 0
186  $numberOfFullLocalizedChildren = 0;
187  $numberOfNotYetLocalizedChildren = 0;
188  foreach ($this->data['parameterArray']['fieldConf']['children'] as $child) {
189  if (!$child['isInlineDefaultLanguageRecordInLocalizedParentContext']) {
190  $numberOfFullLocalizedChildren++;
191  }
192  if ($isLocalizedParent && $child['isInlineDefaultLanguageRecordInLocalizedParentContext']) {
193  $numberOfNotYetLocalizedChildren++;
194  }
195  }
196 
197  if ($isReadOnly || $numberOfFullLocalizedChildren >= ($config['maxitems'] ?? 0)) {
198  $config['inline']['showNewFileReferenceButton'] = false;
199  $config['inline']['showCreateNewRelationButton'] = false;
200  $config['inline']['showOnlineMediaAddButtonStyle'] = false;
201  }
202 
203  $fieldInformationResult = $this->‪renderFieldInformation();
204  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
205 
206  $fieldWizardResult = $this->‪renderFieldWizard();
207  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
208 
209  $sortableRecordUids = $fileReferencesHtml = [];
210  foreach ($this->data['parameterArray']['fieldConf']['children'] as $options) {
211  $options['inlineParentUid'] = $row['uid'];
212  $options['inlineFirstPid'] = $this->data['inlineFirstPid'];
213  $options['inlineParentConfig'] = $config;
214  $options['inlineData'] = ‪$this->fileReferenceData;
215  $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
216  $options['inlineExpandCollapseStateArray'] = $this->data['inlineExpandCollapseStateArray'];
217  $options['renderType'] = ‪FileReferenceContainer::NODE_TYPE_IDENTIFIER;
218  $fileReference = $this->nodeFactory->create($options)->render();
219  $fileReferencesHtml[] = $fileReference['html'];
220  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fileReference, false);
221  if (!$options['isInlineDefaultLanguageRecordInLocalizedParentContext'] && isset($options['databaseRow']['uid'])) {
222  // Don't add record to list of "valid" uids if it is only the default
223  // language record of a not yet localized child
224  $sortableRecordUids[] = $options['databaseRow']['uid'];
225  }
226  }
227 
228  $view = $this->backendViewFactory->create($this->data['request']);
229  $view->assignMultiple([
230  'formFieldIdentifier' => $formFieldIdentifier,
231  'formFieldName' => $formFieldName,
232  'formGroupAttributes' => GeneralUtility::implodeAttributes([
233  'class' => 'form-group',
234  'id' => $formFieldIdentifier,
235  'data-uid' => (string)$row['uid'],
236  'data-local-table' => (string)$top['table'],
237  'data-local-field' => (string)$top['field'],
238  'data-foreign-table' => self::FILE_REFERENCE_TABLE,
239  'data-object-group' => $formFieldIdentifier . '-' . self::FILE_REFERENCE_TABLE,
240  'data-form-field' => $formFieldName,
241  'data-appearance' => (string)json_encode($config['appearance'] ?? ''),
242  ], true),
243  'fieldInformation' => $fieldInformationResult['html'],
244  'fieldWizard' => $fieldWizardResult['html'],
245  'fileReferences' => [
246  'id' => $formFieldIdentifier . '_records',
247  'title' => $languageService->sL(trim($parameterArray['fieldConf']['label'] ?? '')),
248  'records' => implode(LF, $fileReferencesHtml),
249  ],
250  'sortableRecordUids' => implode(',', $sortableRecordUids),
251  'validationRules' => $this->‪getValidationDataAsJsonString([
252  'type' => 'inline',
253  'minitems' => $config['minitems'] ?? null,
254  'maxitems' => $config['maxitems'] ?? null,
255  ]),
256  ]);
257 
258  if (!$isReadOnly && ($config['appearance']['showFileSelectors'] ?? true) !== false) {
260  $fileExtensionFilter = GeneralUtility::makeInstance(FileExtensionFilter::class);
261  $fileExtensionFilter->setAllowedFileExtensions($config['allowed'] ?? null);
262  $fileExtensionFilter->setDisallowedFileExtensions($config['disallowed'] ?? null);
263  $view->assign('fileSelectors', $this->‪getFileSelectors($config, $fileExtensionFilter));
264  $view->assignMultiple($fileExtensionFilter->getFilteredFileExtensions());
265  // Render the localization buttons if needed
266  if ($numberOfNotYetLocalizedChildren) {
267  $view->assignMultiple([
268  'showAllLocalizationLink' => !empty($config['appearance']['showAllLocalizationLink']),
269  'showSynchronizationLink' => !empty($config['appearance']['showSynchronizationLink']),
270  ]);
271  }
272  }
273 
274  $event = $this->eventDispatcher->dispatch(
275  new ‪CustomFileControlsEvent($resultArray, $table, $field, $row, $config, $formFieldIdentifier, $formFieldName)
276  );
277  $resultArray = $event->getResultArray();
278  $controls = $event->getControls();
279 
280  if ($controls !== []) {
281  $view->assign('customControls', [
282  'id' => $formFieldIdentifier . '_customControls',
283  'controls' => implode("\n", $controls),
284  ]);
285  }
286 
287  $resultArray['javaScriptModules'] = array_merge(
288  $resultArray['javaScriptModules'],
289  $this->javaScriptModules,
290  [‪JavaScriptModuleInstruction::create('@typo3/backend/form-engine/container/files-control-container.js')]
291  );
292 
293  $resultArray['html'] = $this->‪wrapWithFieldsetAndLegend($view->render('Form/FilesControlContainer'));
294  return $resultArray;
295  }
296 
300  protected function ‪getFileSelectors(array $inlineConfiguration, ‪FileExtensionFilter $fileExtensionFilter): array
301  {
302  $languageService = $this->‪getLanguageService();
303  $backendUser = $this->‪getBackendUserAuthentication();
304 
305  $currentStructureDomObjectIdPrefix = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
306  $objectPrefix = $currentStructureDomObjectIdPrefix . '-' . ‪self::FILE_REFERENCE_TABLE;
307 
308  $controls = [];
309  if ($inlineConfiguration['appearance']['elementBrowserEnabled'] ?? true) {
310  if ($inlineConfiguration['appearance']['createNewRelationLinkTitle'] ?? false) {
311  $buttonText = $inlineConfiguration['appearance']['createNewRelationLinkTitle'];
312  } else {
313  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.createNewRelation';
314  }
315  $buttonText = $languageService->sL($buttonText);
316  $attributes = [
317  'type' => 'button',
318  'class' => 'btn btn-default t3js-element-browser',
319  'style' => !($inlineConfiguration['inline']['showCreateNewRelationButton'] ?? true) ? 'display: none;' : '',
320  'title' => $buttonText,
321  'data-mode' => 'file',
322  'data-params' => '|||allowed=' . implode(',', $fileExtensionFilter->‪getAllowedFileExtensions() ?? []) . '~disallowed=' . implode(',', $fileExtensionFilter->‪getDisallowedFileExtensions() ?? []) . '|' . $objectPrefix,
323  ];
324  $controls[] = '
325  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
326  ' . $this->iconFactory->getIcon('actions-insert-record', IconSize::SMALL)->render() . '
327  ' . htmlspecialchars($buttonText) . '
328  </button>';
329  }
330 
331  $onlineMediaAllowed = [];
332  foreach ($this->onlineMediaHelperRegistry->getSupportedFileExtensions() as $supportedFileExtension) {
333  if ($fileExtensionFilter->‪isAllowed($supportedFileExtension)) {
334  $onlineMediaAllowed[] = $supportedFileExtension;
335  }
336  }
337 
338  $showUpload = (bool)($inlineConfiguration['appearance']['fileUploadAllowed'] ?? true);
339  $showByUrl = ($inlineConfiguration['appearance']['fileByUrlAllowed'] ?? true) && $onlineMediaAllowed !== [];
340 
341  if (($showUpload || $showByUrl) && ($backendUser->uc['edit_docModuleUpload'] ?? false)) {
342  $folder = $this->defaultUploadFolderResolver->resolve(
343  $backendUser,
344  $this->data['tableName'] === 'pages' ? $this->data['vanillaUid'] : ($this->data['parentPageRow']['uid'] ?? 0),
345  $this->data['tableName'],
346  $this->data['fieldName']
347  );
348  if (
349  $folder instanceof ‪Folder
350  && $folder->‪getStorage()->checkUserActionPermission('add', 'File')
351  ) {
352  if ($showUpload) {
353  if ($inlineConfiguration['appearance']['uploadFilesLinkTitle'] ?? false) {
354  $buttonText = $inlineConfiguration['appearance']['uploadFilesLinkTitle'];
355  } else {
356  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.select-and-submit';
357  }
358  $buttonText = $languageService->sL($buttonText);
359 
360  $attributes = [
361  'type' => 'button',
362  'class' => 'btn btn-default t3js-drag-uploader',
363  'title' => $buttonText,
364  'style' => !($inlineConfiguration['inline']['showCreateNewRelationButton'] ?? true) ? 'display: none;' : '',
365  'data-dropzone-target' => '#' . ‪StringUtility::escapeCssSelector($currentStructureDomObjectIdPrefix),
366  'data-insert-dropzone-before' => '1',
367  'data-file-irre-object' => $objectPrefix,
368  'data-file-allowed' => implode(',', $fileExtensionFilter->‪getAllowedFileExtensions() ?? []),
369  'data-file-disallowed' => implode(',', $fileExtensionFilter->‪getDisallowedFileExtensions() ?? []),
370  'data-target-folder' => $folder->getCombinedIdentifier(),
371  'data-max-file-size' => (string)(GeneralUtility::getMaxUploadFileSize() * 1024),
372  ];
373  $controls[] = '
374  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
375  ' . $this->iconFactory->getIcon('actions-upload', IconSize::SMALL)->render() . '
376  ' . htmlspecialchars($buttonText) . '
377  </button>';
378 
379  $this->javaScriptModules[] = ‪JavaScriptModuleInstruction::create('@typo3/backend/drag-uploader.js');
380  }
381  if ($showByUrl) {
382  if ($inlineConfiguration['appearance']['addMediaLinkTitle'] ?? false) {
383  $buttonText = $inlineConfiguration['appearance']['addMediaLinkTitle'];
384  } else {
385  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.button';
386  }
387  $buttonText = $languageService->sL($buttonText);
388  $attributes = [
389  'type' => 'button',
390  'class' => 'btn btn-default t3js-online-media-add-btn',
391  'title' => $buttonText,
392  'style' => !($inlineConfiguration['inline']['showOnlineMediaAddButtonStyle'] ?? true) ? 'display: none;' : '',
393  'data-target-folder' => $folder->getCombinedIdentifier(),
394  'data-file-irre-object' => $objectPrefix,
395  'data-online-media-allowed' => implode(',', $onlineMediaAllowed),
396  'data-btn-submit' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.placeholder'),
397  'data-placeholder' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.placeholder'),
398  'data-online-media-allowed-help-text' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.allowEmbedSources'),
399  ];
400 
401  // @todo Should be implemented as web component
402  $controls[] = '
403  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
404  ' . $this->iconFactory->getIcon('actions-online-media-add', IconSize::SMALL)->render() . '
405  ' . htmlspecialchars($buttonText) . '
406  </button>';
407 
408  $this->javaScriptModules[] = ‪JavaScriptModuleInstruction::create('@typo3/backend/online-media.js');
409  }
410  }
411  }
412 
413  return $controls;
414  }
415 
420  protected function ‪extractFlexFormParts(string $formElementName): ?array
421  {
422  $flexFormParts = null;
423  $matches = [];
424  if (preg_match('#^data(?:\[[^]]+\]){3}(\[data\](?:\[[^]]+\]){4,})$#', $formElementName, $matches)) {
425  $flexFormParts = ‪GeneralUtility::trimExplode(
426  '][',
427  trim($matches[1], '[]')
428  );
429  }
430  return $flexFormParts;
431  }
432 
434  {
435  return ‪$GLOBALS['LANG'];
436  }
437 }
‪TYPO3\CMS\Core\Resource\OnlineMedia\Helpers\OnlineMediaHelperRegistry
Definition: OnlineMediaHelperRegistry.php:27
‪TYPO3\CMS\Backend\Form\AbstractNode\mergeChildReturnIntoExistingResult
‪array mergeChildReturnIntoExistingResult(array $existing, array $childReturn, bool $mergeHtml=true)
Definition: AbstractNode.php:104
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$javaScriptModules
‪array $javaScriptModules
Definition: FilesControlContainer.php:61
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\getFileSelectors
‪getFileSelectors(array $inlineConfiguration, FileExtensionFilter $fileExtensionFilter)
Definition: FilesControlContainer.php:300
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪TYPO3\CMS\Backend\Form\Container
Definition: AbstractContainer.php:16
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\wrapWithFieldsetAndLegend
‪wrapWithFieldsetAndLegend(string $fieldContent)
Definition: AbstractContainer.php:140
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Page\JavaScriptModuleInstruction
Definition: JavaScriptModuleInstruction.php:23
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$fileReferenceData
‪array $fileReferenceData
Definition: FilesControlContainer.php:56
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\getDisallowedFileExtensions
‪getDisallowedFileExtensions()
Definition: FileExtensionFilter.php:161
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\FILE_REFERENCE_TABLE
‪const FILE_REFERENCE_TABLE
Definition: FilesControlContainer.php:51
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\getLanguageService
‪getLanguageService()
Definition: FilesControlContainer.php:433
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$defaultFieldInformation
‪$defaultFieldInformation
Definition: FilesControlContainer.php:63
‪TYPO3\CMS\Core\Resource\DefaultUploadFolderResolver
Definition: DefaultUploadFolderResolver.php:31
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\getAllowedFileExtensions
‪getAllowedFileExtensions()
Definition: FileExtensionFilter.php:146
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer
Definition: FilesControlContainer.php:48
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\getBackendUserAuthentication
‪getBackendUserAuthentication()
Definition: AbstractContainer.php:149
‪TYPO3\CMS\Core\Resource\Folder
Definition: Folder.php:38
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer
Definition: AbstractContainer.php:29
‪TYPO3\CMS\Core\Resource\Folder\getStorage
‪getStorage()
Definition: Folder.php:139
‪TYPO3\CMS\Core\Utility\GeneralUtility\hmac
‪static string hmac($input, $additionalSecret='')
Definition: GeneralUtility.php:474
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\extractFlexFormParts
‪extractFlexFormParts(string $formElementName)
Definition: FilesControlContainer.php:420
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter
Definition: FileExtensionFilter.php:31
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\isAllowed
‪isAllowed(string $fileExtension)
Definition: FileExtensionFilter.php:121
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\__construct
‪__construct(private readonly IconFactory $iconFactory, private readonly InlineStackProcessor $inlineStackProcessor, private readonly EventDispatcherInterface $eventDispatcher, private readonly OnlineMediaHelperRegistry $onlineMediaHelperRegistry, private readonly DefaultUploadFolderResolver $defaultUploadFolderResolver,)
Definition: FilesControlContainer.php:75
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$defaultFieldWizard
‪$defaultFieldWizard
Definition: FilesControlContainer.php:69
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\renderFieldInformation
‪array renderFieldInformation()
Definition: AbstractContainer.php:52
‪TYPO3\CMS\Backend\Form\Event\CustomFileControlsEvent
Definition: CustomFileControlsEvent.php:24
‪TYPO3\CMS\Backend\Form\Container\FileReferenceContainer\NODE_TYPE_IDENTIFIER
‪const NODE_TYPE_IDENTIFIER
Definition: FileReferenceContainer.php:51
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Backend\Form\AbstractNode\getValidationDataAsJsonString
‪getValidationDataAsJsonString(array $config)
Definition: AbstractNode.php:133
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\NODE_TYPE_IDENTIFIER
‪const NODE_TYPE_IDENTIFIER
Definition: FilesControlContainer.php:49
‪TYPO3\CMS\Core\Utility\StringUtility\escapeCssSelector
‪static escapeCssSelector(string $selector)
Definition: StringUtility.php:69
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Form\InlineStackProcessor
Definition: InlineStackProcessor.php:32
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Utility\StringUtility
Definition: StringUtility.php:24
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\renderFieldWizard
‪array renderFieldWizard()
Definition: AbstractContainer.php:86
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\render
‪array render()
Definition: FilesControlContainer.php:88
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:817
‪TYPO3\CMS\Backend\Form\AbstractNode\initializeResultArray
‪initializeResultArray()
Definition: AbstractNode.php:77