‪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;
26 use TYPO3\CMS\Core\Imaging\IconSize;
36 
49 {
50  private const ‪FILE_REFERENCE_TABLE = 'sys_file_reference';
51 
55  protected array ‪$fileReferenceData = [];
56 
60  protected array ‪$javaScriptModules = [];
61 
63  'tcaDescription' => [
64  'renderType' => 'tcaDescription',
65  ],
66  ];
67 
68  protected ‪$defaultFieldWizard = [
69  'localizationStateSelector' => [
70  'renderType' => 'localizationStateSelector',
71  ],
72  ];
73 
74  public function ‪__construct(
75  private readonly ‪IconFactory $iconFactory,
76  private readonly ‪InlineStackProcessor $inlineStackProcessor,
77  private readonly EventDispatcherInterface $eventDispatcher,
78  private readonly ‪OnlineMediaHelperRegistry $onlineMediaHelperRegistry,
79  private readonly ‪DefaultUploadFolderResolver $defaultUploadFolderResolver,
80  private readonly ‪HashService $hashService,
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  $inlineChildren = $parameterArray['fieldConf']['children'] ?? [];
147 
148  $config['inline']['first'] = $config['inline']['last'] = false;
149  if (is_array($inlineChildren) && $inlineChildren !== []) {
150  $firstChild = $inlineChildren[array_key_first($inlineChildren)] ?? null;
151  if (isset($firstChild['databaseRow']['uid'])) {
152  $config['inline']['first'] = $firstChild['databaseRow']['uid'];
153  }
154  $lastChild = $inlineChildren[array_key_last($inlineChildren)] ?? null;
155  if (isset($lastChild['databaseRow']['uid'])) {
156  $config['inline']['last'] = $lastChild['databaseRow']['uid'];
157  }
158  }
159 
160  $top = $this->inlineStackProcessor->getStructureLevel(0);
161 
162  $this->fileReferenceData['config'][$formFieldIdentifier] = [
164  ];
165  $configJson = (string)json_encode($config);
166  $this->fileReferenceData['config'][$formFieldIdentifier . '-' . ‪self::FILE_REFERENCE_TABLE] = [
167  'min' => $config['minitems'],
168  'max' => $config['maxitems'],
169  'sortable' => $config['appearance']['useSortable'] ?? false,
170  'top' => [
171  'table' => $top['table'],
172  'uid' => $top['uid'],
173  ],
174  'context' => [
175  'config' => $configJson,
176  'hmac' => $this->hashService->hmac($configJson, 'FilesContext'),
177  ],
178  ];
179  $this->fileReferenceData['nested'][$formFieldIdentifier] = $this->data['tabAndInlineStack'];
180 
181  $resultArray['inlineData'] = ‪$this->fileReferenceData;
182 
183  // @todo: It might be a good idea to have something like "isLocalizedRecord" or similar set by a data provider
184  $uidOfDefaultRecord = $row[‪$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField'] ?? null] ?? 0;
185  $isLocalizedParent = $language > 0
186  && ($uidOfDefaultRecord[0] ?? $uidOfDefaultRecord) > 0
188  $numberOfFullLocalizedChildren = 0;
189  $numberOfNotYetLocalizedChildren = 0;
190  foreach ($inlineChildren as $child) {
191  if (!$child['isInlineDefaultLanguageRecordInLocalizedParentContext']) {
192  $numberOfFullLocalizedChildren++;
193  }
194  if ($isLocalizedParent && $child['isInlineDefaultLanguageRecordInLocalizedParentContext']) {
195  $numberOfNotYetLocalizedChildren++;
196  }
197  }
198 
199  if ($isReadOnly || $numberOfFullLocalizedChildren >= ($config['maxitems'] ?? 0)) {
200  $config['inline']['showNewFileReferenceButton'] = false;
201  $config['inline']['showCreateNewRelationButton'] = false;
202  $config['inline']['showOnlineMediaAddButtonStyle'] = false;
203  }
204 
205  $fieldInformationResult = $this->‪renderFieldInformation();
206  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
207 
208  $fieldWizardResult = $this->‪renderFieldWizard();
209  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
210 
211  $sortableRecordUids = $fileReferencesHtml = [];
212  foreach ($inlineChildren as $options) {
213  $options['inlineParentUid'] = $row['uid'];
214  $options['inlineFirstPid'] = $this->data['inlineFirstPid'];
215  $options['inlineParentConfig'] = $config;
216  $options['inlineData'] = ‪$this->fileReferenceData;
217  $options['inlineStructure'] = $this->inlineStackProcessor->getStructure();
218  $options['inlineExpandCollapseStateArray'] = $this->data['inlineExpandCollapseStateArray'];
219  $options['renderType'] = 'fileReferenceContainer';
220  $fileReference = $this->nodeFactory->create($options)->render();
221  $fileReferencesHtml[] = $fileReference['html'];
222  $resultArray = $this->‪mergeChildReturnIntoExistingResult($resultArray, $fileReference, false);
223  if (!$options['isInlineDefaultLanguageRecordInLocalizedParentContext'] && isset($options['databaseRow']['uid'])) {
224  // Don't add record to list of "valid" uids if it is only the default
225  // language record of a not yet localized child
226  $sortableRecordUids[] = $options['databaseRow']['uid'];
227  }
228  }
229 
230  $view = $this->backendViewFactory->create($this->data['request']);
231  $view->assignMultiple([
232  'formFieldIdentifier' => $formFieldIdentifier,
233  'formFieldName' => $formFieldName,
234  'formGroupAttributes' => GeneralUtility::implodeAttributes([
235  'class' => 'form-group',
236  'id' => $formFieldIdentifier,
237  'data-uid' => (string)$row['uid'],
238  'data-local-table' => (string)$top['table'],
239  'data-local-field' => (string)$top['field'],
240  'data-foreign-table' => self::FILE_REFERENCE_TABLE,
241  'data-object-group' => $formFieldIdentifier . '-' . self::FILE_REFERENCE_TABLE,
242  'data-form-field' => $formFieldName,
243  'data-appearance' => (string)json_encode($config['appearance'] ?? ''),
244  ], true),
245  'fieldInformation' => $fieldInformationResult['html'],
246  'fieldWizard' => $fieldWizardResult['html'],
247  'fileReferences' => [
248  'id' => $formFieldIdentifier . '_records',
249  'title' => $languageService->sL(trim($parameterArray['fieldConf']['label'] ?? '')),
250  'records' => implode(LF, $fileReferencesHtml),
251  ],
252  'sortableRecordUids' => implode(',', $sortableRecordUids),
253  'validationRules' => $this->‪getValidationDataAsJsonString([
254  'type' => 'inline',
255  'minitems' => $config['minitems'] ?? null,
256  'maxitems' => $config['maxitems'] ?? null,
257  ]),
258  ]);
259 
260  if (!$isReadOnly && ($config['appearance']['showFileSelectors'] ?? true) !== false) {
262  $fileExtensionFilter = GeneralUtility::makeInstance(FileExtensionFilter::class);
263  $fileExtensionFilter->setAllowedFileExtensions($config['allowed'] ?? null);
264  $fileExtensionFilter->setDisallowedFileExtensions($config['disallowed'] ?? null);
265  $view->assign('fileSelectors', $this->‪getFileSelectors($config, $fileExtensionFilter));
266  $view->assignMultiple($fileExtensionFilter->getFilteredFileExtensions());
267  // Render the localization buttons if needed
268  if ($numberOfNotYetLocalizedChildren) {
269  $view->assignMultiple([
270  'showAllLocalizationLink' => !empty($config['appearance']['showAllLocalizationLink']),
271  'showSynchronizationLink' => !empty($config['appearance']['showSynchronizationLink']),
272  ]);
273  }
274  }
275 
276  $event = $this->eventDispatcher->dispatch(
277  new ‪CustomFileControlsEvent($resultArray, $table, $field, $row, $config, $formFieldIdentifier, $formFieldName)
278  );
279  $resultArray = $event->getResultArray();
280  $controls = $event->getControls();
281 
282  if ($controls !== []) {
283  $view->assign('customControls', [
284  'id' => $formFieldIdentifier . '_customControls',
285  'controls' => implode("\n", $controls),
286  ]);
287  }
288 
289  $resultArray['javaScriptModules'] = array_merge(
290  $resultArray['javaScriptModules'],
291  $this->javaScriptModules,
292  [‪JavaScriptModuleInstruction::create('@typo3/backend/form-engine/container/files-control-container.js')]
293  );
294 
295  $resultArray['html'] = $this->‪wrapWithFieldsetAndLegend($view->render('Form/FilesControlContainer'));
296  return $resultArray;
297  }
298 
302  protected function ‪getFileSelectors(array $inlineConfiguration, ‪FileExtensionFilter $fileExtensionFilter): array
303  {
304  $languageService = $this->‪getLanguageService();
305  $backendUser = $this->‪getBackendUserAuthentication();
306 
307  $currentStructureDomObjectIdPrefix = $this->inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
308  $objectPrefix = $currentStructureDomObjectIdPrefix . '-' . ‪self::FILE_REFERENCE_TABLE;
309 
310  $controls = [];
311  if ($inlineConfiguration['appearance']['elementBrowserEnabled'] ?? true) {
312  if ($inlineConfiguration['appearance']['createNewRelationLinkTitle'] ?? false) {
313  $buttonText = $inlineConfiguration['appearance']['createNewRelationLinkTitle'];
314  } else {
315  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.createNewRelation';
316  }
317  $buttonText = $languageService->sL($buttonText);
318  $attributes = [
319  'type' => 'button',
320  'class' => 'btn btn-default t3js-element-browser',
321  'style' => !($inlineConfiguration['inline']['showCreateNewRelationButton'] ?? true) ? 'display: none;' : '',
322  'title' => $buttonText,
323  'data-mode' => 'file',
324  'data-params' => '|||allowed=' . implode(',', $fileExtensionFilter->‪getAllowedFileExtensions() ?? []) . '~disallowed=' . implode(',', $fileExtensionFilter->‪getDisallowedFileExtensions() ?? []) . '|' . $objectPrefix,
325  ];
326  $controls[] = '
327  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
328  ' . $this->iconFactory->getIcon('actions-insert-record', IconSize::SMALL)->render() . '
329  ' . htmlspecialchars($buttonText) . '
330  </button>';
331  }
332 
333  $onlineMediaAllowed = [];
334  foreach ($this->onlineMediaHelperRegistry->getSupportedFileExtensions() as $supportedFileExtension) {
335  if ($fileExtensionFilter->‪isAllowed($supportedFileExtension)) {
336  $onlineMediaAllowed[] = $supportedFileExtension;
337  }
338  }
339 
340  $showUpload = (bool)($inlineConfiguration['appearance']['fileUploadAllowed'] ?? true);
341  $showByUrl = ($inlineConfiguration['appearance']['fileByUrlAllowed'] ?? true) && $onlineMediaAllowed !== [];
342 
343  if (($showUpload || $showByUrl) && ($backendUser->uc['edit_docModuleUpload'] ?? false)) {
344  $folder = $this->defaultUploadFolderResolver->resolve(
345  $backendUser,
346  $this->data['tableName'] === 'pages' ? $this->data['vanillaUid'] : ($this->data['parentPageRow']['uid'] ?? 0),
347  $this->data['tableName'],
348  $this->data['fieldName']
349  );
350  if (
351  $folder instanceof ‪Folder
352  && $folder->‪getStorage()->checkUserActionPermission('add', 'File')
353  ) {
354  if ($showUpload) {
355  if ($inlineConfiguration['appearance']['uploadFilesLinkTitle'] ?? false) {
356  $buttonText = $inlineConfiguration['appearance']['uploadFilesLinkTitle'];
357  } else {
358  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:file_upload.select-and-submit';
359  }
360  $buttonText = $languageService->sL($buttonText);
361 
362  $attributes = [
363  'type' => 'button',
364  'class' => 'btn btn-default t3js-drag-uploader',
365  'title' => $buttonText,
366  'style' => !($inlineConfiguration['inline']['showCreateNewRelationButton'] ?? true) ? 'display: none;' : '',
367  'data-dropzone-target' => '#' . ‪StringUtility::escapeCssSelector($currentStructureDomObjectIdPrefix),
368  'data-insert-dropzone-before' => '1',
369  'data-file-irre-object' => $objectPrefix,
370  'data-file-allowed' => implode(',', $fileExtensionFilter->‪getAllowedFileExtensions() ?? []),
371  'data-file-disallowed' => implode(',', $fileExtensionFilter->‪getDisallowedFileExtensions() ?? []),
372  'data-target-folder' => $folder->getCombinedIdentifier(),
373  'data-max-file-size' => (string)(GeneralUtility::getMaxUploadFileSize() * 1024),
374  ];
375  $controls[] = '
376  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
377  ' . $this->iconFactory->getIcon('actions-upload', IconSize::SMALL)->render() . '
378  ' . htmlspecialchars($buttonText) . '
379  </button>';
380 
381  $this->javaScriptModules[] = ‪JavaScriptModuleInstruction::create('@typo3/backend/drag-uploader.js');
382  }
383  if ($showByUrl) {
384  if ($inlineConfiguration['appearance']['addMediaLinkTitle'] ?? false) {
385  $buttonText = $inlineConfiguration['appearance']['addMediaLinkTitle'];
386  } else {
387  $buttonText = 'LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.button';
388  }
389  $buttonText = $languageService->sL($buttonText);
390  $attributes = [
391  'type' => 'button',
392  'class' => 'btn btn-default t3js-online-media-add-btn',
393  'title' => $buttonText,
394  'style' => !($inlineConfiguration['inline']['showOnlineMediaAddButtonStyle'] ?? true) ? 'display: none;' : '',
395  'data-target-folder' => $folder->getCombinedIdentifier(),
396  'data-file-irre-object' => $objectPrefix,
397  'data-online-media-allowed' => implode(',', $onlineMediaAllowed),
398  'data-btn-submit' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.placeholder'),
399  'data-placeholder' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:online_media.new_media.placeholder'),
400  'data-online-media-allowed-help-text' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:cm.allowEmbedSources'),
401  ];
402 
403  // @todo Should be implemented as web component
404  $controls[] = '
405  <button ' . GeneralUtility::implodeAttributes($attributes, true) . '>
406  ' . $this->iconFactory->getIcon('actions-online-media-add', IconSize::SMALL)->render() . '
407  ' . htmlspecialchars($buttonText) . '
408  </button>';
409 
410  $this->javaScriptModules[] = ‪JavaScriptModuleInstruction::create('@typo3/backend/online-media.js');
411  }
412  }
413  }
414 
415  return $controls;
416  }
417 
422  protected function ‪extractFlexFormParts(string $formElementName): ?array
423  {
424  $flexFormParts = null;
425  $matches = [];
426  if (preg_match('#^data(?:\[[^]]+\]){3}(\[data\](?:\[[^]]+\]){4,})$#', $formElementName, $matches)) {
427  $flexFormParts = ‪GeneralUtility::trimExplode(
428  '][',
429  trim($matches[1], '[]')
430  );
431  }
432  return $flexFormParts;
433  }
434 
436  {
437  return ‪$GLOBALS['LANG'];
438  }
439 }
‪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, private readonly HashService $hashService,)
Definition: FilesControlContainer.php:74
‪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:60
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\getFileSelectors
‪getFileSelectors(array $inlineConfiguration, FileExtensionFilter $fileExtensionFilter)
Definition: FilesControlContainer.php:302
‪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:55
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\getDisallowedFileExtensions
‪getDisallowedFileExtensions()
Definition: FileExtensionFilter.php:160
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\FILE_REFERENCE_TABLE
‪const FILE_REFERENCE_TABLE
Definition: FilesControlContainer.php:50
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\getLanguageService
‪getLanguageService()
Definition: FilesControlContainer.php:435
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$defaultFieldInformation
‪$defaultFieldInformation
Definition: FilesControlContainer.php:62
‪TYPO3\CMS\Core\Resource\DefaultUploadFolderResolver
Definition: DefaultUploadFolderResolver.php:33
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\getAllowedFileExtensions
‪getAllowedFileExtensions()
Definition: FileExtensionFilter.php:145
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer
Definition: FilesControlContainer.php:49
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\getBackendUserAuthentication
‪getBackendUserAuthentication()
Definition: AbstractContainer.php:150
‪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\Backend\Form\Container\FilesControlContainer\extractFlexFormParts
‪extractFlexFormParts(string $formElementName)
Definition: FilesControlContainer.php:422
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter
Definition: FileExtensionFilter.php:30
‪TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter\isAllowed
‪isAllowed(string $fileExtension)
Definition: FileExtensionFilter.php:120
‪TYPO3\CMS\Backend\Form\Container\FilesControlContainer\$defaultFieldWizard
‪$defaultFieldWizard
Definition: FilesControlContainer.php:68
‪TYPO3\CMS\Backend\Form\Container\AbstractContainer\renderFieldInformation
‪array renderFieldInformation()
Definition: AbstractContainer.php:52
‪TYPO3\CMS\Backend\Form\Event\CustomFileControlsEvent
Definition: CustomFileControlsEvent.php:24
‪$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\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\Core\Page\JavaScriptModuleInstruction\create
‪static create(string $name, ?string $exportName=null)
Definition: JavaScriptModuleInstruction.php:47
‪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\Core\Crypto\HashService
Definition: HashService.php:27
‪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:822
‪TYPO3\CMS\Backend\Form\AbstractNode\initializeResultArray
‪initializeResultArray()
Definition: AbstractNode.php:77