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