‪TYPO3CMS  9.5
AbstractItemProvider.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Doctrine\DBAL\DBALException;
39 
45 {
54  protected function ‪resolveItemProcessorFunction(array $result, $fieldName, array $items)
55  {
56  $table = $result['tableName'];
57  $config = $result['processedTca']['columns'][$fieldName]['config'];
58 
59  $pageTsProcessorParameters = null;
60  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['itemsProcFunc.'])) {
61  $pageTsProcessorParameters = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['itemsProcFunc.'];
62  }
63  $processorParameters = [
64  // Function manipulates $items directly and return nothing
65  'items' => &$items,
66  'config' => $config,
67  'TSconfig' => $pageTsProcessorParameters,
68  'table' => $table,
69  'row' => $result['databaseRow'],
70  'field' => $fieldName,
71  ];
72  if (!empty($result['flexParentDatabaseRow'])) {
73  $processorParameters['flexParentDatabaseRow'] = $result['flexParentDatabaseRow'];
74  }
75 
76  try {
77  GeneralUtility::callUserFunction($config['itemsProcFunc'], $processorParameters, $this);
78  } catch (\‪Exception $exception) {
79  // The itemsProcFunc method may throw an exception, create a flash message if so
80  $languageService = $this->‪getLanguageService();
81  $fieldLabel = $fieldName;
82  if (!empty($result['processedTca']['columns'][$fieldName]['label'])) {
83  $fieldLabel = $languageService->sL($result['processedTca']['columns'][$fieldName]['label']);
84  }
85  $message = sprintf(
86  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.items_proc_func_error'),
87  $fieldLabel,
88  $exception->getMessage()
89  );
91  $flashMessage = GeneralUtility::makeInstance(
92  FlashMessage::class,
93  $message,
94  '',
96  true
97  );
99  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
100  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
101  $defaultFlashMessageQueue->enqueue($flashMessage);
102  }
103 
104  return $items;
105  }
106 
120  protected function ‪addItemsFromPageTsConfig(array $result, $fieldName, array $items)
121  {
122  $table = $result['tableName'];
123  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
124  && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
125  ) {
126  $addItemsArray = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'];
127  foreach ($addItemsArray as $value => $label) {
128  // If the value ends with a dot, it is a subelement like "34.icon = mylabel.png", skip it
129  if (substr($value, -1) === '.') {
130  continue;
131  }
132  // Check if value "34 = mylabel" also has a "34.icon = myImage.png"
133  $iconIdentifier = null;
134  if (isset($addItemsArray[$value . '.'])
135  && is_array($addItemsArray[$value . '.'])
136  && !empty($addItemsArray[$value . '.']['icon'])
137  ) {
138  $iconIdentifier = $addItemsArray[$value . '.']['icon'];
139  }
140  $items[] = [$label, $value, $iconIdentifier];
141  }
142  }
143  return $items;
144  }
145 
157  protected function ‪addItemsFromSpecial(array $result, $fieldName, array $items)
158  {
159  // Guard
160  if (empty($result['processedTca']['columns'][$fieldName]['config']['special'])
161  || !is_string($result['processedTca']['columns'][$fieldName]['config']['special'])
162  ) {
163  return $items;
164  }
165 
166  $languageService = $this->‪getLanguageService();
167  ‪$iconRegistry = GeneralUtility::makeInstance(IconRegistry::class);
168  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
169 
170  $special = $result['processedTca']['columns'][$fieldName]['config']['special'];
171  switch (true) {
172  case $special === 'tables':
173  foreach (‪$GLOBALS['TCA'] as $currentTable => $_) {
174  if (!empty(‪$GLOBALS['TCA'][$currentTable]['ctrl']['adminOnly'])) {
175  // Hide "admin only" tables
176  continue;
177  }
178  $label = !empty(‪$GLOBALS['TCA'][$currentTable]['ctrl']['title']) ? ‪$GLOBALS['TCA'][$currentTable]['ctrl']['title'] : '';
179  $icon = $iconFactory->mapRecordTypeToIconIdentifier($currentTable, []);
180  $helpText = [];
181  $languageService->loadSingleTableDescription($currentTable);
182  // @todo: check if this actually works, currently help texts are missing
183  $helpTextArray = ‪$GLOBALS['TCA_DESCR'][$currentTable]['columns'][''];
184  if (!empty($helpTextArray['description'])) {
185  $helpText['description'] = $helpTextArray['description'];
186  }
187  $items[] = [$label, $currentTable, $icon, $helpText];
188  }
189  break;
190  case $special === 'pagetypes':
191  if (isset(‪$GLOBALS['TCA']['pages']['columns']['doktype']['config']['items'])
192  && is_array(‪$GLOBALS['TCA']['pages']['columns']['doktype']['config']['items'])
193  ) {
194  $specialItems = ‪$GLOBALS['TCA']['pages']['columns']['doktype']['config']['items'];
195  foreach ($specialItems as $specialItem) {
196  if (!is_array($specialItem) || $specialItem[1] === '--div--') {
197  // Skip non arrays and divider items
198  continue;
199  }
200  $label = $specialItem[0];
201  $value = $specialItem[1];
202  $icon = $iconFactory->mapRecordTypeToIconIdentifier('pages', ['doktype' => $specialItem[1]]);
203  $items[] = [$label, $value, $icon];
204  }
205  }
206  break;
207  case $special === 'exclude':
208  $excludeArrays = $this->‪getExcludeFields();
209  foreach ($excludeArrays as $excludeArray) {
210  // If the field comes from a FlexForm, the syntax is more complex
211  if ($excludeArray['origin'] === 'flexForm') {
212  // The field comes from a plugins FlexForm
213  // Add header if not yet set for plugin section
214  if (!isset($items[$excludeArray['sectionHeader']])) {
215  // there is no icon handling for plugins - we take the icon from the table
216  $icon = $iconFactory->mapRecordTypeToIconIdentifier($excludeArray['table'], []);
217  $items[$excludeArray['sectionHeader']] = [
218  $excludeArray['sectionHeader'],
219  '--div--',
220  $icon
221  ];
222  }
223  } else {
224  // Add header if not yet set for table
225  if (!isset($items[$excludeArray['table']])) {
226  $icon = $iconFactory->mapRecordTypeToIconIdentifier($excludeArray['table'], []);
227  $items[$excludeArray['table']] = [
228  ‪$GLOBALS['TCA'][$excludeArray['table']]['ctrl']['title'],
229  '--div--',
230  $icon
231  ];
232  }
233  }
234  // Add help text
235  $helpText = [];
236  $languageService->loadSingleTableDescription($excludeArray['table']);
237  $helpTextArray = ‪$GLOBALS['TCA_DESCR'][$excludeArray['table']]['columns'][$excludeArray['table']] ?? [];
238  if (!empty($helpTextArray['description'])) {
239  $helpText['description'] = $helpTextArray['description'];
240  }
241  // Item configuration:
242  $items[] = [
243  rtrim($excludeArray['origin'] === 'flexForm' ? $excludeArray['fieldLabel'] : $languageService->sL(‪$GLOBALS['TCA'][$excludeArray['table']]['columns'][$excludeArray['fieldName']]['label']), ':') . ' (' . $excludeArray['fieldName'] . ')',
244  $excludeArray['table'] . ':' . $excludeArray['fullField'],
245  'empty-empty',
246  $helpText
247  ];
248  }
249  break;
250  case $special === 'explicitValues':
251  $theTypes = $this->‪getExplicitAuthFieldValues();
252  ‪$icons = [
253  'ALLOW' => 'status-status-permission-granted',
254  'DENY' => 'status-status-permission-denied'
255  ];
256  // Traverse types:
257  foreach ($theTypes as $tableFieldKey => $theTypeArrays) {
258  if (!empty($theTypeArrays['items'])) {
259  // Add header:
260  $items[] = [
261  $theTypeArrays['tableFieldLabel'],
262  '--div--',
263  ];
264  // Traverse options for this field:
265  foreach ($theTypeArrays['items'] as $itemValue => $itemContent) {
266  // Add item to be selected:
267  $items[] = [
268  '[' . $itemContent[2] . '] ' . $itemContent[1],
269  $tableFieldKey . ':' . preg_replace('/[:|,]/', '', $itemValue) . ':' . $itemContent[0],
270  ‪$icons[$itemContent[0]]
271  ];
272  }
273  }
274  }
275  break;
276  case $special === 'languages':
277  foreach ($result['systemLanguageRows'] as $language) {
278  if ($language['uid'] !== -1) {
279  $items[] = [
280  0 => $language['title'],
281  1 => $language['uid'],
282  2 => $language['flagIconIdentifier']
283  ];
284  }
285  }
286  break;
287  case $special === 'custom':
288  $customOptions = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['customPermOptions'];
289  if (is_array($customOptions)) {
290  foreach ($customOptions as $coKey => $coValue) {
291  if (is_array($coValue['items'])) {
292  // Add header:
293  $items[] = [
294  $languageService->sL($coValue['header']),
295  '--div--'
296  ];
297  // Traverse items:
298  foreach ($coValue['items'] as $itemKey => $itemCfg) {
299  $icon = 'empty-empty';
300  $helpText = [];
301  if (!empty($itemCfg[1])) {
302  if (‪$iconRegistry->isRegistered($itemCfg[1])) {
303  // Use icon identifier when registered
304  $icon = $itemCfg[1];
305  }
306  }
307  if (!empty($itemCfg[2])) {
308  $helpText['description'] = $languageService->sL($itemCfg[2]);
309  }
310  $items[] = [
311  $languageService->sL($itemCfg[0]),
312  $coKey . ':' . preg_replace('/[:|,]/', '', $itemKey),
313  $icon,
314  $helpText
315  ];
316  }
317  }
318  }
319  }
320  break;
321  case $special === 'modListGroup' || $special === 'modListUser':
323  $loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
324  $loadModules->load(‪$GLOBALS['TBE_MODULES']);
325  $modList = $special === 'modListUser' ? $loadModules->modListUser : $loadModules->modListGroup;
326  if (is_array($modList)) {
327  foreach ($modList as $theMod) {
328  $moduleLabels = $loadModules->getLabelsForModule($theMod);
329  $moduleArray = GeneralUtility::trimExplode('_', $theMod, true);
330  $mainModule = $moduleArray[0] ?? '';
331  $subModule = $moduleArray[1] ?? '';
332  // Icon:
333  if (!empty($subModule)) {
334  $icon = $loadModules->modules[$mainModule]['sub'][$subModule]['iconIdentifier'];
335  } else {
336  $icon = $loadModules->modules[$theMod]['iconIdentifier'];
337  }
338  // Add help text
339  $helpText = [
340  'title' => $languageService->sL($moduleLabels['shortdescription']),
341  'description' => $languageService->sL($moduleLabels['description'])
342  ];
343 
344  $label = '';
345  // Add label for main module if this is a submodule
346  if (!empty($subModule)) {
347  $mainModuleLabels = $loadModules->getLabelsForModule($mainModule);
348  $label .= $languageService->sL($mainModuleLabels['title']) . '>';
349  }
350  // Add modules own label now
351  $label .= $languageService->sL($moduleLabels['title']);
352 
353  // Item configuration
354  $items[] = [$label, $theMod, $icon, $helpText];
355  }
356  }
357  break;
358  default:
359  throw new \UnexpectedValueException(
360  'Unknown special value ' . $special . ' for field ' . $fieldName . ' of table ' . $result['tableName'],
361  1439298496
362  );
363  }
364  return $items;
365  }
366 
378  protected function ‪addItemsFromFolder(array $result, $fieldName, array $items)
379  {
380  if (empty($result['processedTca']['columns'][$fieldName]['config']['fileFolder'])
381  || !is_string($result['processedTca']['columns'][$fieldName]['config']['fileFolder'])
382  ) {
383  return $items;
384  }
385 
386  $fileFolderRaw = $result['processedTca']['columns'][$fieldName]['config']['fileFolder'];
387  $fileFolder = GeneralUtility::getFileAbsFileName($fileFolderRaw);
388  if ($fileFolder === '') {
389  throw new \RuntimeException(
390  'Invalid folder given for item processing: ' . $fileFolderRaw . ' for table ' . $result['tableName'] . ', field ' . $fieldName,
391  1479399227
392  );
393  }
394  $fileFolder = rtrim($fileFolder, '/') . '/';
395 
396  if (@is_dir($fileFolder)) {
397  $fileExtensionList = '';
398  if (!empty($result['processedTca']['columns'][$fieldName]['config']['fileFolder_extList'])
399  && is_string($result['processedTca']['columns'][$fieldName]['config']['fileFolder_extList'])
400  ) {
401  $fileExtensionList = $result['processedTca']['columns'][$fieldName]['config']['fileFolder_extList'];
402  }
403  $recursionLevels = isset($result['processedTca']['columns'][$fieldName]['config']['fileFolder_recursions'])
404  ? ‪MathUtility::forceIntegerInRange($result['processedTca']['columns'][$fieldName]['config']['fileFolder_recursions'], 0, 99)
405  : 99;
406  $fileArray = GeneralUtility::getAllFilesAndFoldersInPath([], $fileFolder, $fileExtensionList, 0, $recursionLevels);
407  $fileArray = GeneralUtility::removePrefixPathFromList($fileArray, $fileFolder);
408  foreach ($fileArray as $fileReference) {
409  $fileInformation = pathinfo($fileReference);
410  $icon = GeneralUtility::inList(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], strtolower($fileInformation['extension']))
411  ? $fileFolder . $fileReference
412  : '';
413  $items[] = [
414  $fileReference,
415  $fileReference,
416  $icon
417  ];
418  }
419  }
420 
421  return $items;
422  }
423 
435  protected function ‪addItemsFromForeignTable(array $result, $fieldName, array $items)
436  {
437  // Guard
438  if (empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
439  || !is_string($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
440  ) {
441  return $items;
442  }
443 
444  $languageService = $this->‪getLanguageService();
445 
446  $foreignTable = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'];
447 
448  if (!isset(‪$GLOBALS['TCA'][$foreignTable]) || !is_array(‪$GLOBALS['TCA'][$foreignTable])) {
449  throw new \UnexpectedValueException(
450  'Field ' . $fieldName . ' of table ' . $result['tableName'] . ' reference to foreign table '
451  . $foreignTable . ', but this table is not defined in TCA',
452  1439569743
453  );
454  }
455 
456  $queryBuilder = $this->‪buildForeignTableQueryBuilder($result, $fieldName);
457  try {
458  $queryResult = $queryBuilder->execute();
459  } catch (DBALException $e) {
460  $databaseError = $e->getPrevious()->getMessage();
461  }
462 
463  // Early return on error with flash message
464  if (!empty($databaseError)) {
465  $msg = $databaseError . '. ';
466  $msg .= $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch');
467  $msgTitle = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch_title');
469  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $msg, $msgTitle, ‪FlashMessage::ERROR, true);
471  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
473  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
474  $defaultFlashMessageQueue->enqueue($flashMessage);
475  return $items;
476  }
477 
478  $labelPrefix = '';
479  if (!empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'])) {
480  $labelPrefix = $result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'];
481  $labelPrefix = $languageService->sL($labelPrefix);
482  }
483 
484  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
485  $fileRepository = GeneralUtility::makeInstance(FileRepository::class);
486 
487  while ($foreignRow = $queryResult->fetch()) {
488  ‪BackendUtility::workspaceOL($foreignTable, $foreignRow);
489  if (is_array($foreignRow)) {
490  // If the foreign table sets selicon_field, this field can contain an image
491  // that represents this specific row.
492  $iconFieldName = '';
493  $isReferenceField = false;
494  if (!empty(‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'])) {
495  $iconFieldName = ‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'];
496  if (isset(‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['type'])
497  && ‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['type'] === 'inline'
498  && ‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['foreign_table'] === 'sys_file_reference'
499  ) {
500  $isReferenceField = true;
501  }
502  }
503  $icon = '';
504  if ($isReferenceField) {
505  $references = $fileRepository->findByRelation($foreignTable, $iconFieldName, $foreignRow['uid']);
506  if (is_array($references) && !empty($references)) {
507  $icon = reset($references);
508  $icon = $icon->getPublicUrl();
509  }
510  } else {
511  $iconPath = '';
512  if (!empty(‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field_path'])) {
513  $iconPath = ‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field_path'];
514  }
515  if ($iconFieldName && $iconPath && $foreignRow[$iconFieldName]) {
516  // Prepare the row icon if available
517  $iParts = GeneralUtility::trimExplode(',', $foreignRow[$iconFieldName], true);
518  $icon = $iconPath . '/' . trim($iParts[0]);
519  } else {
520  // Else, determine icon based on record type, or a generic fallback
521  $icon = $iconFactory->mapRecordTypeToIconIdentifier($foreignTable, $foreignRow);
522  }
523  }
524  // Add the item
525  $items[] = [
526  $labelPrefix . ‪BackendUtility::getRecordTitle($foreignTable, $foreignRow),
527  $foreignRow['uid'],
528  $icon
529  ];
530  }
531  }
532 
533  return $items;
534  }
535 
546  protected function ‪removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
547  {
548  $table = $result['tableName'];
549  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
550  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
551  ) {
552  return $items;
553  }
554 
555  // If keepItems is set but is an empty list all current items get removed
556  if ($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'] === '') {
557  return [];
558  }
559 
561  $items,
562  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'],
563  function ($value) {
564  return $value[1];
565  }
566  );
567  }
568 
579  protected function ‪removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
580  {
581  $table = $result['tableName'];
582  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
583  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
584  || $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'] === ''
585  ) {
586  return $items;
587  }
588 
589  $removeItems = array_flip(GeneralUtility::trimExplode(
590  ',',
591  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'],
592  true
593  ));
594  foreach ($items as $key => $itemValues) {
595  if (isset($removeItems[$itemValues[1]])) {
596  unset($items[$key]);
597  }
598  }
599 
600  return $items;
601  }
602 
613  protected function ‪removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
614  {
615  // Guard clause returns if not a language field is handled
616  if (empty($result['processedTca']['ctrl']['languageField'])
617  || $result['processedTca']['ctrl']['languageField'] !== $fieldName
618  ) {
619  return $items;
620  }
621 
622  $backendUser = $this->‪getBackendUser();
623  foreach ($items as $key => $itemValues) {
624  if (!$backendUser->checkLanguageAccess($itemValues[1])) {
625  unset($items[$key]);
626  }
627  }
628 
629  return $items;
630  }
631 
642  protected function ‪removeItemsByUserAuthMode(array $result, $fieldName, array $items)
643  {
644  // Guard clause returns early if no authMode field is configured
645  if (!isset($result['processedTca']['columns'][$fieldName]['config']['authMode'])
646  || !is_string($result['processedTca']['columns'][$fieldName]['config']['authMode'])
647  ) {
648  return $items;
649  }
650 
651  $backendUser = $this->‪getBackendUser();
652  $authMode = $result['processedTca']['columns'][$fieldName]['config']['authMode'];
653  foreach ($items as $key => $itemValues) {
654  // @todo: checkAuthMode() uses $GLOBAL access for "individual" authMode - get rid of this
655  if (!$backendUser->checkAuthMode($result['tableName'], $fieldName, $itemValues[1], $authMode)) {
656  unset($items[$key]);
657  }
658  }
659 
660  return $items;
661  }
662 
673  protected function ‪removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
674  {
675  $table = $result['tableName'];
676  $backendUser = $this->‪getBackendUser();
677  // Guard clause returns if not correct table and field or if user is admin
678  if ($table !== 'pages' || $fieldName !== 'doktype' || $backendUser->isAdmin()
679  ) {
680  return $items;
681  }
682 
683  $allowedPageTypes = $backendUser->groupData['pagetypes_select'];
684  foreach ($items as $key => $itemValues) {
685  if (!GeneralUtility::inList($allowedPageTypes, $itemValues[1])) {
686  unset($items[$key]);
687  }
688  }
689 
690  return $items;
691  }
692 
703  protected function ‪removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
704  {
705  $referencedTableName = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'] ?? null;
706  if ($referencedTableName !== 'sys_file_storage') {
707  return $items;
708  }
709 
710  $allowedStorageIds = array_map(
711  function (\‪TYPO3\CMS\Core\Resource\ResourceStorage $storage) {
712  return $storage->getUid();
713  },
715  );
716 
717  return array_filter(
718  $items,
719  function (array $item) use ($allowedStorageIds) {
720  $itemValue = $item[1] ?? null;
721  return empty($itemValue)
722  || in_array((int)$itemValue, $allowedStorageIds, true);
723  }
724  );
725  }
726 
734  protected function ‪getExcludeFields()
735  {
736  $languageService = $this->‪getLanguageService();
737  $finalExcludeArray = [];
738 
739  // Fetch translations for table names
740  $tableToTranslation = [];
741  // All TCA keys
742  foreach (‪$GLOBALS['TCA'] as $table => $conf) {
743  $tableToTranslation[$table] = $languageService->sL($conf['ctrl']['title']);
744  }
745  // Sort by translations
746  asort($tableToTranslation);
747  foreach ($tableToTranslation as $table => $translatedTable) {
748  $excludeArrayTable = [];
749 
750  // All field names configured and not restricted to admins
751  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])
752  && empty(‪$GLOBALS['TCA'][$table]['ctrl']['adminOnly'])
753  && (empty(‪$GLOBALS['TCA'][$table]['ctrl']['rootLevel']) || !empty(‪$GLOBALS['TCA'][$table]['ctrl']['security']['ignoreRootLevelRestriction']))
754  ) {
755  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $field => $_) {
756  if (isset(‪$GLOBALS['TCA'][$table]['columns'][$field]['exclude']) && (bool)‪$GLOBALS['TCA'][$table]['columns'][$field]['exclude']) {
757  // Get human readable names of fields
758  $translatedField = $languageService->sL(‪$GLOBALS['TCA'][$table]['columns'][$field]['label']);
759  // Add entry, key 'labels' needed for sorting
760  $excludeArrayTable[] = [
761  'labels' => $translatedTable . ':' . $translatedField,
762  'sectionHeader' => $translatedTable,
763  'table' => $table,
764  'tableField' => $field,
765  'fieldName' => $field,
766  'fullField' => $field,
767  'fieldLabel' => $translatedField,
768  'origin' => 'tca',
769  ];
770  }
771  }
772  }
773  // All FlexForm fields
774  $flexFormArray = $this->‪getRegisteredFlexForms($table);
775  foreach ($flexFormArray as $tableField => $flexForms) {
776  // Prefix for field label, e.g. "Plugin Options:"
777  $labelPrefix = '';
778  if (!empty(‪$GLOBALS['TCA'][$table]['columns'][$tableField]['label'])) {
779  $labelPrefix = $languageService->sL(‪$GLOBALS['TCA'][$table]['columns'][$tableField]['label']);
780  }
781  // Get all sheets
782  foreach ($flexForms as $extIdent => ‪$extConf) {
783  // Get all fields in sheet
784  foreach (‪$extConf['sheets'] as $sheetName => $sheet) {
785  if (empty($sheet['ROOT']['el']) || !is_array($sheet['ROOT']['el'])) {
786  continue;
787  }
788  foreach ($sheet['ROOT']['el'] as $pluginFieldName => $field) {
789  // Use only fields that have exclude flag set
790  if (empty($field['TCEforms']['exclude'])) {
791  continue;
792  }
793  $fieldLabel = !empty($field['TCEforms']['label'])
794  ? $languageService->sL($field['TCEforms']['label'])
795  : $pluginFieldName;
796  $excludeArrayTable[] = [
797  'labels' => trim($translatedTable . ' ' . $labelPrefix . ' ' . $extIdent, ': ') . ':' . $fieldLabel,
798  'sectionHeader' => trim($translatedTable . ' ' . $labelPrefix . ' ' . $extIdent, ':'),
799  'table' => $table,
800  'tableField' => $tableField,
801  'extIdent' => $extIdent,
802  'fieldName' => $pluginFieldName,
803  'fullField' => $tableField . ';' . $extIdent . ';' . $sheetName . ';' . $pluginFieldName,
804  'fieldLabel' => $fieldLabel,
805  'origin' => 'flexForm',
806  ];
807  }
808  }
809  }
810  }
811  // Sort fields by the translated value
812  if (!empty($excludeArrayTable)) {
813  usort($excludeArrayTable, function (array $array1, array $array2) {
814  $array1 = reset($array1);
815  $array2 = reset($array2);
816  if (is_string($array1) && is_string($array2)) {
817  return strcasecmp($array1, $array2);
818  }
819  return 0;
820  });
821  $finalExcludeArray = array_merge($finalExcludeArray, $excludeArrayTable);
822  }
823  }
824 
825  return $finalExcludeArray;
826  }
827 
846  protected function ‪getRegisteredFlexForms($table)
847  {
848  if (empty($table) || empty(‪$GLOBALS['TCA'][$table]['columns'])) {
849  return [];
850  }
851  $flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
852  $flexForms = [];
853  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $tableField => $fieldConf) {
854  if (!empty($fieldConf['config']['type']) && !empty($fieldConf['config']['ds']) && $fieldConf['config']['type'] === 'flex') {
855  $flexForms[$tableField] = [];
856  foreach (array_keys($fieldConf['config']['ds']) as $flexFormKey) {
857  // Get extension identifier (uses second value if it's not empty, "list" or "*", else first one)
858  $identFields = GeneralUtility::trimExplode(',', $flexFormKey);
859  $extIdent = $identFields[0];
860  if (!empty($identFields[1]) && $identFields[1] !== 'list' && $identFields[1] !== '*') {
861  $extIdent = $identFields[1];
862  }
863  $flexFormDataStructureIdentifier = json_encode([
864  'type' => 'tca',
865  'tableName' => $table,
866  'fieldName' => $tableField,
867  'dataStructureKey' => $flexFormKey,
868  ]);
869  try {
870  $dataStructure = $flexFormTools->parseDataStructureByIdentifier($flexFormDataStructureIdentifier);
871  $flexForms[$tableField][$extIdent] = $dataStructure;
872  } catch (‪InvalidIdentifierException $e) {
873  // Deliberately empty: The DS identifier is guesswork and the flex ds parser throws
874  // this exception if it can not resolve to a valid data structure. This is "ok" here
875  // and the exception is just eaten.
876  }
877  }
878  }
879  }
880  return $flexForms;
881  }
882 
889  protected function ‪getExplicitAuthFieldValues()
890  {
891  $languageService = static::getLanguageService();
892  $adLabel = [
893  'ALLOW' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.allow'),
894  'DENY' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.deny')
895  ];
896  $allowDenyOptions = [];
897  foreach (‪$GLOBALS['TCA'] as $table => $_) {
898  // All field names configured:
899  if (is_array(‪$GLOBALS['TCA'][$table]['columns'])) {
900  foreach (‪$GLOBALS['TCA'][$table]['columns'] as $field => $__) {
901  $fieldConfig = ‪$GLOBALS['TCA'][$table]['columns'][$field]['config'];
902  if ($fieldConfig['type'] === 'select' && $fieldConfig['authMode']) {
903  // Check for items
904  if (is_array($fieldConfig['items'])) {
905  // Get Human Readable names of fields and table:
906  $allowDenyOptions[$table . ':' . $field]['tableFieldLabel'] =
907  $languageService->sL(‪$GLOBALS['TCA'][$table]['ctrl']['title']) . ': '
908  . $languageService->sL(‪$GLOBALS['TCA'][$table]['columns'][$field]['label']);
909  foreach ($fieldConfig['items'] as $iVal) {
910  $itemIdentifier = (string)$iVal[1];
911  // Values '' and '--div--' are not controlled by this setting.
912  if ($itemIdentifier === '' || $itemIdentifier === '--div--') {
913  continue;
914  }
915  // Find iMode
916  $iMode = '';
917  switch ((string)$fieldConfig['authMode']) {
918  case 'explicitAllow':
919  $iMode = 'ALLOW';
920  break;
921  case 'explicitDeny':
922  $iMode = 'DENY';
923  break;
924  case 'individual':
925  if (isset($iVal[4]) && $iVal[4] === 'EXPL_ALLOW') {
926  $iMode = 'ALLOW';
927  } elseif (isset($iVal[4]) && $iVal[4] === 'EXPL_DENY') {
928  $iMode = 'DENY';
929  }
930  break;
931  }
932  // Set iMode
933  if ($iMode) {
934  $allowDenyOptions[$table . ':' . $field]['items'][$itemIdentifier] = [
935  $iMode,
936  $languageService->sL($iVal[0]),
937  $adLabel[$iMode]
938  ];
939  }
940  }
941  }
942  }
943  }
944  }
945  }
946  return $allowDenyOptions;
947  }
948 
957  protected function ‪buildForeignTableQueryBuilder(array $result, string $localFieldName): ‪QueryBuilder
958  {
959  $backendUser = $this->‪getBackendUser();
960 
961  $foreignTableName = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table'];
962  $foreignTableClauseArray = $this->‪processForeignTableClause($result, $foreignTableName, $localFieldName);
963 
964  $fieldList = ‪BackendUtility::getCommonSelectFields($foreignTableName, $foreignTableName . '.');
966  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
967  ->getQueryBuilderForTable($foreignTableName);
968 
969  $queryBuilder->getRestrictions()
970  ->removeAll()
971  ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
972 
973  $queryBuilder
974  ->select(...GeneralUtility::trimExplode(',', $fieldList, true))
975  ->from($foreignTableName)
976  ->where($foreignTableClauseArray['WHERE']);
977 
978  if (!empty($foreignTableClauseArray['GROUPBY'])) {
979  $queryBuilder->groupBy(...$foreignTableClauseArray['GROUPBY']);
980  }
981 
982  if (!empty($foreignTableClauseArray['ORDERBY'])) {
983  foreach ($foreignTableClauseArray['ORDERBY'] as $orderPair) {
984  list($fieldName, $order) = $orderPair;
985  $queryBuilder->addOrderBy($fieldName, $order);
986  }
987  } elseif (!empty(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby'])) {
988  $orderByClauses = ‪QueryHelper::parseOrderBy(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby']);
989  foreach ($orderByClauses as $orderByClause) {
990  if (!empty($orderByClause[0])) {
991  $queryBuilder->addOrderBy($foreignTableName . '.' . $orderByClause[0], $orderByClause[1]);
992  }
993  }
994  }
995 
996  if (!empty($foreignTableClauseArray['LIMIT'])) {
997  if (!empty($foreignTableClauseArray['LIMIT'][1])) {
998  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][1]);
999  $queryBuilder->setFirstResult($foreignTableClauseArray['LIMIT'][0]);
1000  } elseif (!empty($foreignTableClauseArray['LIMIT'][0])) {
1001  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][0]);
1002  }
1003  }
1004 
1005  // rootLevel = -1 means that elements can be on the rootlevel OR on any page (pid!=-1)
1006  // rootLevel = 0 means that elements are not allowed on root level
1007  // rootLevel = 1 means that elements are only on the root level (pid=0)
1008  $rootLevel = 0;
1009  if (isset(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'])) {
1010  $rootLevel = (int)‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'];
1011  }
1012 
1013  if ($rootLevel === -1) {
1014  $queryBuilder->andWhere(
1015  $queryBuilder->expr()->neq(
1016  $foreignTableName . '.pid',
1017  $queryBuilder->createNamedParameter(-1, \PDO::PARAM_INT)
1018  )
1019  );
1020  } elseif ($rootLevel === 1) {
1021  $queryBuilder->andWhere(
1022  $queryBuilder->expr()->eq(
1023  $foreignTableName . '.pid',
1024  $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
1025  )
1026  );
1027  } else {
1028  $queryBuilder->andWhere($backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
1029  if ($foreignTableName !== 'pages') {
1030  $queryBuilder
1031  ->from('pages')
1032  ->andWhere(
1033  $queryBuilder->expr()->eq(
1034  'pages.uid',
1035  $queryBuilder->quoteIdentifier($foreignTableName . '.pid')
1036  )
1037  );
1038  }
1039  }
1040 
1041  return $queryBuilder;
1042  }
1043 
1060  protected function ‪processForeignTableClause(array $result, $foreignTableName, $localFieldName)
1061  {
1062  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($foreignTableName);
1063  $localTable = $result['tableName'];
1064  $effectivePid = $result['effectivePid'];
1065 
1066  $foreignTableClause = '';
1067  if (!empty($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
1068  && is_string($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
1069  ) {
1070  $foreignTableClause = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'];
1071  // Replace possible markers in query
1072  if (strstr($foreignTableClause, '###REC_FIELD_')) {
1073  // " AND table.field='###REC_FIELD_field1###' AND ..." -> array(" AND table.field='", "field1###' AND ...")
1074  $whereClauseParts = explode('###REC_FIELD_', $foreignTableClause);
1075  foreach ($whereClauseParts as $key => $value) {
1076  if ($key !== 0) {
1077  // "field1###' AND ..." -> array("field1", "' AND ...")
1078  $whereClauseSubParts = explode('###', $value, 2);
1079  // @todo: Throw exception if there is no value? What happens for NEW records?
1080  $databaseRowKey = empty($result['flexParentDatabaseRow']) ? 'databaseRow' : 'flexParentDatabaseRow';
1081  $rowFieldValue = $result[$databaseRowKey][$whereClauseSubParts[0]] ?? '';
1082  if (is_array($rowFieldValue)) {
1083  // If a select or group field is used here, it may have been processed already and
1084  // is now an array containing uid + table + title + row.
1085  // See TcaGroup data provider for details.
1086  // Pick the first one (always on 0), and use uid only.
1087  $rowFieldValue = $rowFieldValue[0]['uid'] ?? $rowFieldValue[0];
1088  }
1089  if (substr($whereClauseParts[0], -1) === '\'' && $whereClauseSubParts[1][0] === '\'') {
1090  $whereClauseParts[0] = substr($whereClauseParts[0], 0, -1);
1091  $whereClauseSubParts[1] = substr($whereClauseSubParts[1], 1);
1092  }
1093  $whereClauseParts[$key] = $connection->quote($rowFieldValue) . $whereClauseSubParts[1];
1094  }
1095  }
1096  $foreignTableClause = implode('', $whereClauseParts);
1097  }
1098  if (strpos($foreignTableClause, '###CURRENT_PID###') !== false) {
1099  // Use pid from parent page clause if in flex form context
1100  if (!empty($result['flexParentDatabaseRow']['pid'])) {
1101  $effectivePid = $result['flexParentDatabaseRow']['pid'];
1102  } elseif (!$effectivePid && !empty($result['databaseRow']['pid'])) {
1103  // Use pid from database row if in inline context
1104  $effectivePid = $result['databaseRow']['pid'];
1105  }
1106  }
1107 
1108  $siteRootUid = 0;
1109  foreach ($result['rootline'] as $rootlinePage) {
1110  if (!empty($rootlinePage['is_siteroot'])) {
1111  $siteRootUid = (int)$rootlinePage['uid'];
1112  break;
1113  }
1114  }
1115 
1116  $pageTsConfigId = 0;
1117  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'])
1118  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID']
1119  ) {
1120  $pageTsConfigId = (int)$result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'];
1121  }
1122 
1123  $pageTsConfigIdList = 0;
1124  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'])
1125  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST']
1126  ) {
1127  $pageTsConfigIdList = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'];
1128  }
1129  $pageTsConfigIdListArray = GeneralUtility::trimExplode(',', $pageTsConfigIdList, true);
1130  $pageTsConfigIdList = [];
1131  foreach ($pageTsConfigIdListArray as $pageTsConfigIdListElement) {
1132  if (‪MathUtility::canBeInterpretedAsInteger($pageTsConfigIdListElement)) {
1133  $pageTsConfigIdList[] = (int)$pageTsConfigIdListElement;
1134  }
1135  }
1136  $pageTsConfigIdList = implode(',', $pageTsConfigIdList);
1137 
1138  $pageTsConfigString = '';
1139  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'])
1140  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR']
1141  ) {
1142  $pageTsConfigString = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'];
1143  $pageTsConfigString = $connection->quote($pageTsConfigString);
1144  }
1145 
1146  $foreignTableClause = str_replace(
1147  [
1148  '###CURRENT_PID###',
1149  '###THIS_UID###',
1150  '###SITEROOT###',
1151  '###PAGE_TSCONFIG_ID###',
1152  '###PAGE_TSCONFIG_IDLIST###',
1153  '\'###PAGE_TSCONFIG_STR###\'',
1154  '###PAGE_TSCONFIG_STR###'
1155  ],
1156  [
1157  (int)$effectivePid,
1158  (int)$result['databaseRow']['uid'],
1159  $siteRootUid,
1160  $pageTsConfigId,
1161  $pageTsConfigIdList,
1162  $pageTsConfigString,
1163  $pageTsConfigString
1164  ],
1165  $foreignTableClause
1166  );
1167  }
1168 
1169  // Split the clause into an array with keys WHERE, GROUPBY, ORDERBY, LIMIT
1170  // Prepend a space to make sure "[[:space:]]+" will find a space there for the first element.
1171  $foreignTableClause = ' ' . $foreignTableClause;
1172  $foreignTableClauseArray = [
1173  'WHERE' => '',
1174  'GROUPBY' => '',
1175  'ORDERBY' => '',
1176  'LIMIT' => '',
1177  ];
1178  // Find LIMIT
1179  $reg = [];
1180  if (preg_match('/^(.*)[[:space:]]+LIMIT[[:space:]]+([[:alnum:][:space:],._]+)$/is', $foreignTableClause, $reg)) {
1181  $foreignTableClauseArray['LIMIT'] = GeneralUtility::intExplode(',', trim($reg[2]), true);
1182  $foreignTableClause = $reg[1];
1183  }
1184  // Find ORDER BY
1185  $reg = [];
1186  if (preg_match('/^(.*)[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
1187  $foreignTableClauseArray['ORDERBY'] = ‪QueryHelper::parseOrderBy(trim($reg[2]));
1188  $foreignTableClause = $reg[1];
1189  }
1190  // Find GROUP BY
1191  $reg = [];
1192  if (preg_match('/^(.*)[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
1193  $foreignTableClauseArray['GROUPBY'] = ‪QueryHelper::parseGroupBy(trim($reg[2]));
1194  $foreignTableClause = $reg[1];
1195  }
1196  // Rest is assumed to be "WHERE" clause
1197  $foreignTableClauseArray['WHERE'] = ‪QueryHelper::stripLogicalOperatorPrefix($foreignTableClause);
1198 
1199  return $foreignTableClauseArray;
1200  }
1201 
1209  protected function ‪processDatabaseFieldValue(array $row, $fieldName)
1210  {
1211  $currentDatabaseValues = array_key_exists($fieldName, $row)
1212  ? $row[$fieldName]
1213  : '';
1214  if (!is_array($currentDatabaseValues)) {
1215  $currentDatabaseValues = GeneralUtility::trimExplode(',', $currentDatabaseValues, true);
1216  }
1217  return $currentDatabaseValues;
1218  }
1219 
1231  protected function ‪processSelectFieldValue(array $result, $fieldName, array $staticValues)
1232  {
1233  $fieldConfig = $result['processedTca']['columns'][$fieldName];
1234 
1235  $currentDatabaseValueArray = array_key_exists($fieldName, $result['databaseRow']) ? $result['databaseRow'][$fieldName] : [];
1236  $newDatabaseValueArray = [];
1237 
1238  // Add all values that were defined by static methods and do not come from the relation
1239  // e.g. TCA, TSconfig, itemProcFunc etc.
1240  foreach ($currentDatabaseValueArray as $value) {
1241  if (isset($staticValues[$value])) {
1242  $newDatabaseValueArray[] = $value;
1243  }
1244  }
1245 
1246  if (isset($fieldConfig['config']['foreign_table']) && !empty($fieldConfig['config']['foreign_table'])) {
1248  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
1249  $relationHandler->registerNonTableValues = !empty($fieldConfig['config']['allowNonIdValues']);
1250  if (!empty($fieldConfig['config']['MM']) && $result['command'] !== 'new') {
1251  // MM relation
1252  $relationHandler->start(
1253  implode(',', $currentDatabaseValueArray),
1254  $fieldConfig['config']['foreign_table'],
1255  $fieldConfig['config']['MM'],
1256  $result['databaseRow']['uid'],
1257  $result['tableName'],
1258  $fieldConfig['config']
1259  );
1260  $newDatabaseValueArray = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
1261  } else {
1262  // Non MM relation
1263  // If not dealing with MM relations, use default live uid, not versioned uid for record relations
1264  $relationHandler->start(
1265  implode(',', $currentDatabaseValueArray),
1266  $fieldConfig['config']['foreign_table'],
1267  '',
1268  $this->‪getLiveUid($result),
1269  $result['tableName'],
1270  $fieldConfig['config']
1271  );
1272  $databaseIds = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
1273  // remove all items from the current DB values if not available as relation or static value anymore
1274  $newDatabaseValueArray = array_values(array_intersect($currentDatabaseValueArray, $databaseIds));
1275  }
1276  }
1277 
1278  if ($fieldConfig['config']['multiple'] ?? false) {
1279  return $newDatabaseValueArray;
1280  }
1281  return array_unique($newDatabaseValueArray);
1282  }
1283 
1295  public function ‪translateLabels(array $result, array $itemArray, $table, $fieldName)
1296  {
1297  $languageService = $this->‪getLanguageService();
1298 
1299  foreach ($itemArray as $key => $item) {
1300  if (!isset($dynamicItems[$key])) {
1301  $staticValues[$item[1]] = $item;
1302  }
1303  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$item[1]])
1304  && !empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$item[1]])
1305  ) {
1306  $label = $languageService->sL($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$item[1]]);
1307  } else {
1308  $label = $languageService->sL(trim($item[0]));
1309  }
1310  $value = strlen((string)$item[1]) > 0 ? $item[1] : '';
1311  $icon = !empty($item[2]) ? $item[2] : null;
1312  $helpText = null;
1313  if (!empty($item[3])) {
1314  if (\is_string($item[3])) {
1315  $helpText = $languageService->sL($item[3]);
1316  } else {
1317  $helpText = $item[3];
1318  }
1319  }
1320  $itemArray[$key] = [
1321  $label,
1322  $value,
1323  $icon,
1324  $helpText
1325  ];
1326  }
1327 
1328  return $itemArray;
1329  }
1330 
1342  public function ‪sanitizeItemArray($itemArray, $tableName, $fieldName)
1343  {
1344  if (!is_array($itemArray)) {
1345  $itemArray = [];
1346  }
1347  foreach ($itemArray as $item) {
1348  if (!is_array($item)) {
1349  throw new \UnexpectedValueException(
1350  'An item in field ' . $fieldName . ' of table ' . $tableName . ' is not an array as expected',
1351  1439288036
1352  );
1353  }
1354  }
1355 
1356  return $itemArray;
1357  }
1358 
1367  protected function ‪getLiveUid(array $result)
1368  {
1369  $table = $result['tableName'];
1370  $row = $result['databaseRow'];
1371  $uid = $row['uid'];
1372  if (!empty($result['processedTca']['ctrl']['versioningWS'])
1373  && $result['pid'] === -1
1374  ) {
1375  if (empty($row['t3ver_oid'])) {
1376  throw new \UnexpectedValueException(
1377  'No t3ver_oid found for record ' . $row['uid'] . ' on table ' . $table,
1378  1440066481
1379  );
1380  }
1381  $uid = $row['t3ver_oid'];
1382  }
1383  return $uid;
1384  }
1385 
1389  protected function ‪getLanguageService()
1390  {
1391  return ‪$GLOBALS['LANG'];
1392  }
1393 
1397  protected function ‪getBackendUser()
1398  {
1399  return ‪$GLOBALS['BE_USER'];
1400  }
1401 }
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\sanitizeItemArray
‪array sanitizeItemArray($itemArray, $tableName, $fieldName)
Definition: AbstractItemProvider.php:1342
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:42
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\buildForeignTableQueryBuilder
‪QueryBuilder buildForeignTableQueryBuilder(array $result, string $localFieldName)
Definition: AbstractItemProvider.php:957
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromPageTsConfig
‪array addItemsFromPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:120
‪TYPO3\CMS\Core\Utility\ArrayUtility\keepItemsInArray
‪static array keepItemsInArray(array $array, $keepItems, $getValueFunc=null)
Definition: ArrayUtility.php:678
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: AbstractItemProvider.php:1397
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:73
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserLanguageFieldRestriction
‪array removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:613
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility\getCommonSelectFields
‪static string getCommonSelectFields($table, $prefix='', $fields=[])
Definition: BackendUtility.php:2397
‪TYPO3
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseGroupBy
‪static array string[] parseGroupBy(string $input)
Definition: QueryHelper.php:100
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLanguageService
‪LanguageService getLanguageService()
Definition: AbstractItemProvider.php:1389
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\translateLabels
‪array translateLabels(array $result, array $itemArray, $table, $fieldName)
Definition: AbstractItemProvider.php:1295
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromSpecial
‪array addItemsFromSpecial(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:157
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:31
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromForeignTable
‪array addItemsFromForeignTable(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:435
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\getFileStorages
‪TYPO3 CMS Core Resource ResourceStorage[] getFileStorages()
Definition: BackendUserAuthentication.php:1851
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:23
‪TYPO3\CMS\Core\Database\Query\QueryBuilder
Definition: QueryBuilder.php:47
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processForeignTableClause
‪array processForeignTableClause(array $result, $foreignTableName, $localFieldName)
Definition: AbstractItemProvider.php:1060
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getExcludeFields
‪array getExcludeFields()
Definition: AbstractItemProvider.php:734
‪TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidIdentifierException
Definition: InvalidIdentifierException.php:21
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:30
‪TYPO3\CMS\Core\Resource\FileRepository
Definition: FileRepository.php:32
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserStorageRestriction
‪array removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:703
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\resolveItemProcessorFunction
‪array resolveItemProcessorFunction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:54
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByDoktypeUserRestriction
‪array removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:673
‪TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools
Definition: FlexFormTools.php:36
‪TYPO3\CMS\Backend\Module\ModuleLoader
Definition: ModuleLoader.php:32
‪TYPO3\CMS\Backend\Utility\BackendUtility\getRecordTitle
‪static string getRecordTitle($table, $row, $prep=false, $forceResult=true)
Definition: BackendUtility.php:1811
‪TYPO3\CMS\Core\Imaging\IconRegistry
Definition: IconRegistry.php:34
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:32
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:2
‪TYPO3\CMS\Backend\Utility\BackendUtility
Definition: BackendUtility.php:72
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByKeepItemsPageTsConfig
‪array removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:546
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processDatabaseFieldValue
‪array processDatabaseFieldValue(array $row, $fieldName)
Definition: AbstractItemProvider.php:1209
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:22
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processSelectFieldValue
‪array processSelectFieldValue(array $result, $fieldName, array $staticValues)
Definition: AbstractItemProvider.php:1231
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:163
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getExplicitAuthFieldValues
‪array getExplicitAuthFieldValues()
Definition: AbstractItemProvider.php:889
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Backend\Utility\BackendUtility\workspaceOL
‪static workspaceOL($table, &$row, $wsid=-99, $unsetMovePointers=false)
Definition: BackendUtility.php:4048
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:26
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getRegisteredFlexForms
‪array getRegisteredFlexForms($table)
Definition: AbstractItemProvider.php:846
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserAuthMode
‪array removeItemsByUserAuthMode(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:642
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLiveUid
‪int getLiveUid(array $result)
Definition: AbstractItemProvider.php:1367
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:44
‪$extConf
‪$extConf
Definition: ext_localconf.php:50
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Messaging\FlashMessageQueue
Definition: FlashMessageQueue.php:25
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromFolder
‪array addItemsFromFolder(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:378
‪$icons
‪$icons
Definition: ext_localconf.php:77
‪$iconRegistry
‪$iconRegistry
Definition: ext_localconf.php:76
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:25
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider
Definition: AbstractItemProvider.php:45
‪TYPO3\CMS\Core\Messaging\AbstractMessage\ERROR
‪const ERROR
Definition: AbstractMessage.php:29
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByRemoveItemsPageTsConfig
‪array removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:579