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