‪TYPO3CMS  ‪main
AbstractItemProvider.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Doctrine\DBAL\Exception as DBALException;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
23 use TYPO3\CMS\Core\Database\Query\QueryBuilder;
44 
50 {
59  protected function ‪resolveItemProcessorFunction(array $result, $fieldName, array $items)
60  {
61  $table = $result['tableName'];
62  $config = $result['processedTca']['columns'][$fieldName]['config'];
63 
64  $pageTsProcessorParameters = null;
65  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['itemsProcFunc.'])) {
66  $pageTsProcessorParameters = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['itemsProcFunc.'];
67  }
68  $processorParameters = [
69  // Function manipulates $items directly and return nothing
70  'items' => &$items,
71  'config' => $config,
72  'TSconfig' => $pageTsProcessorParameters,
73  'table' => $table,
74  'row' => $result['databaseRow'],
75  'field' => $fieldName,
76  // IMPORTANT: Below fields are only available in FormEngine context.
77  // They are not used by the DataHandler when processing itemsProcFunc
78  // for checking if a submitted value is valid. This means, in case
79  // an item is added based on one of these fields, it won't be persisted
80  // by the DataHandler. This currently(!) only concerns columns of type "check"
81  // and type "radio", see checkValueForCheck() and checkValueForRadio().
82  // Therefore, no limitations when using those fields with other types
83  // like "select", but this may change in the future.
84  'inlineParentUid' => $result['inlineParentUid'],
85  'inlineParentTableName' => $result['inlineParentTableName'],
86  'inlineParentFieldName' => $result['inlineParentFieldName'],
87  'inlineParentConfig' => $result['inlineParentConfig'],
88  'inlineTopMostParentUid' => $result['inlineTopMostParentUid'],
89  'inlineTopMostParentTableName' => $result['inlineTopMostParentTableName'],
90  'inlineTopMostParentFieldName' => $result['inlineTopMostParentFieldName'],
91  ];
92  if (!empty($result['flexParentDatabaseRow'])) {
93  $processorParameters['flexParentDatabaseRow'] = $result['flexParentDatabaseRow'];
94  }
95 
96  try {
97  $items = array_map(
98  fn(array $item): ‪SelectItem => ‪SelectItem::fromTcaItemArray($item, $config['type']),
99  $items
100  );
101  GeneralUtility::callUserFunction($config['itemsProcFunc'], $processorParameters, $this);
102  $items = array_map(
103  fn(‪SelectItem|array $item): ‪SelectItem => $item instanceof ‪SelectItem ? $item : ‪SelectItem::fromTcaItemArray($item, $config['type']),
104  $processorParameters['items']
105  );
106  } catch (\‪Exception $exception) {
107  // The itemsProcFunc method may throw an exception, create a flash message if so
108  $languageService = $this->‪getLanguageService();
109  $fieldLabel = $fieldName;
110  if (!empty($result['processedTca']['columns'][$fieldName]['label'])) {
111  $fieldLabel = $languageService->sL($result['processedTca']['columns'][$fieldName]['label']);
112  }
113  $message = sprintf(
114  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.items_proc_func_error'),
115  $fieldLabel,
116  $exception->getMessage()
117  );
118  $flashMessage = GeneralUtility::makeInstance(
119  FlashMessage::class,
120  $message,
121  '',
122  ContextualFeedbackSeverity::ERROR,
123  true
124  );
125  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
126  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
127  $defaultFlashMessageQueue->enqueue($flashMessage);
128  }
129 
130  return $items;
131  }
132 
146  protected function ‪addItemsFromPageTsConfig(array $result, $fieldName, array $items)
147  {
148  $table = $result['tableName'];
149  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
150  && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
151  ) {
152  $addItemsArray = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'];
153  foreach ($addItemsArray as $value => $label) {
154  // If the value ends with a dot, it is a subelement like "34.icon = mylabel.png", skip it
155  if (str_ends_with($value, '.')) {
156  continue;
157  }
158  // Check if value "34 = mylabel" also has a "34.icon = my-icon-identifier"
159  // or "34.group = my-group-identifier"
160  $iconIdentifier = null;
161  $group = null;
162  if (is_array($addItemsArray[$value . '.'] ?? null)) {
163  if (!empty($addItemsArray[$value . '.']['icon'])) {
164  $iconIdentifier = $addItemsArray[$value . '.']['icon'];
165  }
166  if (!empty($addItemsArray[$value . '.']['group'])) {
167  $group = $addItemsArray[$value . '.']['group'];
168  }
169  }
170 
171  $items[] = [
172  'label' => $label,
173  'value' => $value,
174  'icon' => $iconIdentifier,
175  'group' => $group,
176  ];
177  }
178  }
179  return $items;
180  }
181 
193  protected function ‪addItemsFromFolder(array $result, $fieldName, array $items)
194  {
195  if (empty($result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig']['folder'])
196  || !is_string($result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig']['folder'])
197  ) {
198  return $items;
199  }
200 
201  $tableName = $result['tableName'];
202  $fileFolderConfig = $result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig'];
203  $fileFolderTSconfig = $result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['config.']['fileFolderConfig.'] ?? [];
204 
205  if (is_array($fileFolderTSconfig) && $fileFolderTSconfig !== []) {
206  if ($fileFolderTSconfig['folder'] ?? false) {
207  $fileFolderConfig['folder'] = $fileFolderTSconfig['folder'];
208  }
209  if (isset($fileFolderTSconfig['allowedExtensions'])) {
210  $fileFolderConfig['allowedExtensions'] = $fileFolderTSconfig['allowedExtensions'];
211  }
212  if (isset($fileFolderTSconfig['depth'])) {
213  $fileFolderConfig['depth'] = (int)$fileFolderTSconfig['depth'];
214  }
215  }
216 
217  $folderRaw = $fileFolderConfig['folder'];
218  $folder = GeneralUtility::getFileAbsFileName($folderRaw);
219  if ($folder === '') {
220  throw new \RuntimeException(
221  'Invalid folder given for item processing: ' . $folderRaw . ' for table ' . $tableName . ', field ' . $fieldName,
222  1479399227
223  );
224  }
225  $folder = rtrim($folder, '/') . '/';
226 
227  if (@is_dir($folder)) {
228  $allowedExtensions = '';
229  if (!empty($fileFolderConfig['allowedExtensions']) && is_string($fileFolderConfig['allowedExtensions'])) {
230  $allowedExtensions = $fileFolderConfig['allowedExtensions'];
231  }
232  $depth = isset($fileFolderConfig['depth'])
233  ? ‪MathUtility::forceIntegerInRange($fileFolderConfig['depth'], 0, 99)
234  : 99;
235  $fileArray = GeneralUtility::getAllFilesAndFoldersInPath([], $folder, $allowedExtensions, false, $depth);
236  $fileArray = GeneralUtility::removePrefixPathFromList($fileArray, $folder);
237  foreach ($fileArray as $fileReference) {
238  $fileInformation = pathinfo($fileReference);
239  $icon = ‪GeneralUtility::inList(‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], strtolower($fileInformation['extension']))
240  ? $folder . $fileReference
241  : '';
242  $items[] = [
243  'label' => $fileReference,
244  'value' => $fileReference,
245  'icon' => $icon,
246  ];
247  }
248  }
249 
250  return $items;
251  }
252 
265  protected function ‪addItemsFromForeignTable(array $result, $fieldName, array $items, bool $includeFullRows = false)
266  {
267  $databaseError = null;
268  $queryResult = null;
269  // Guard
270  if (empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
271  || !is_string($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
272  ) {
273  return $items;
274  }
275 
276  $languageService = $this->‪getLanguageService();
277 
278  $foreignTable = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'];
279 
280  if (!isset(‪$GLOBALS['TCA'][$foreignTable]) || !is_array(‪$GLOBALS['TCA'][$foreignTable])) {
281  throw new \UnexpectedValueException(
282  'Field ' . $fieldName . ' of table ' . $result['tableName'] . ' reference to foreign table '
283  . $foreignTable . ', but this table is not defined in TCA',
284  1439569743
285  );
286  }
287 
288  $queryBuilder = $this->‪buildForeignTableQueryBuilder($result, $fieldName, $includeFullRows);
289  try {
290  $queryResult = $queryBuilder->executeQuery();
291  } catch (DBALException $e) {
292  $databaseError = $e->getPrevious()->getMessage();
293  }
294 
295  // Early return on error with flash message
296  if (!empty($databaseError)) {
297  $msg = $databaseError . '. ';
298  $msg .= $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch');
299  $msgTitle = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch_title');
300  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $msg, $msgTitle, ContextualFeedbackSeverity::ERROR, true);
301  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
302  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
303  $defaultFlashMessageQueue->enqueue($flashMessage);
304  return $items;
305  }
306 
307  $labelPrefix = '';
308  if (!empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'])) {
309  $labelPrefix = $result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'];
310  $labelPrefix = $languageService->sL($labelPrefix);
311  }
312 
313  $fileRepository = GeneralUtility::makeInstance(FileRepository::class);
314  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
315 
316  $allForeignRows = $queryResult->fetchAllAssociative();
317  // Find all possible versioned records of the current IDs, so we do not need to overlay each record
318  // This way, workspaceOL() does not need to be called for each record.
319  $workspaceId = $this->‪getBackendUser()->workspace;
320  $doOverlaysForRecords = BackendUtility::getPossibleWorkspaceVersionIdsOfLiveRecordIds($foreignTable, array_column($allForeignRows, 'uid'), $workspaceId);
321 
322  foreach ($allForeignRows as $foreignRow) {
323  // Only do workspace overlays when a versioned record exists.
324  if (isset($foreignRow['uid']) && isset($doOverlaysForRecords[(int)$foreignRow['uid']])) {
325  BackendUtility::workspaceOL($foreignTable, $foreignRow, $workspaceId);
326  }
327  // Only proceed in case the row was not unset and we don't deal with a delete placeholder
328  if (is_array($foreignRow)
329  && VersionState::tryFrom($foreignRow['t3ver_state'] ?? 0) !== VersionState::DELETE_PLACEHOLDER
330  ) {
331  // If the foreign table sets selicon_field, this field can contain an image
332  // that represents this specific row.
333  $iconFieldName = '';
334  $isFileReference = false;
335  if (!empty(‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'])) {
336  $iconFieldName = ‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'];
337  if ((‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['type'] ?? '') === 'file') {
338  $isFileReference = true;
339  }
340  }
341  $icon = '';
342  if ($isFileReference) {
343  $references = $fileRepository->findByRelation($foreignTable, $iconFieldName, $foreignRow['uid']);
344  if (is_array($references) && !empty($references)) {
345  $icon = reset($references);
346  $icon = $icon->getPublicUrl();
347  }
348  } else {
349  // Else, determine icon based on record type, or a generic fallback
350  $icon = $iconFactory->mapRecordTypeToIconIdentifier($foreignTable, $foreignRow);
351  }
352  $item = [
353  'label' => $labelPrefix . BackendUtility::getRecordTitle($foreignTable, $foreignRow),
354  'value' => $foreignRow['uid'],
355  'icon' => $icon,
356  ];
357  if ($includeFullRows) {
358  // @todo: This is part of the category tree performance hack
359  $item['_row'] = $foreignRow;
360  }
361  $items[] = $item;
362  }
363  }
364 
365  return $items;
366  }
367 
378  protected function ‪removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
379  {
380  $table = $result['tableName'];
381  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
382  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
383  ) {
384  return $items;
385  }
386 
387  // If keepItems is set but is an empty list all current items get removed
388  if ($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'] === '') {
389  return [];
390  }
391 
392  return ArrayUtility::keepItemsInArray(
393  $items,
394  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'],
395  static function ($value) {
396  return $value['value'];
397  }
398  );
399  }
400 
411  protected function ‪removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
412  {
413  $table = $result['tableName'];
414  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
415  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
416  || $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'] === ''
417  ) {
418  return $items;
419  }
420 
421  $removeItems = array_flip(GeneralUtility::trimExplode(
422  ',',
423  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'],
424  true
425  ));
426  foreach ($items as $key => $itemValues) {
427  if (isset($removeItems[$itemValues['value']])) {
428  unset($items[$key]);
429  }
430  }
431 
432  return $items;
433  }
434 
445  protected function ‪removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
446  {
447  // Guard clause returns if not a language field is handled
448  if (empty($result['processedTca']['ctrl']['languageField'])
449  || $result['processedTca']['ctrl']['languageField'] !== $fieldName
450  ) {
451  return $items;
452  }
453 
454  $backendUser = $this->‪getBackendUser();
455  foreach ($items as $key => $itemValues) {
456  if (!$backendUser->checkLanguageAccess($itemValues['value'])) {
457  unset($items[$key]);
458  }
459  }
460 
461  return $items;
462  }
463 
474  protected function ‪removeItemsByUserAuthMode(array $result, $fieldName, array $items)
475  {
476  // Guard clause returns early if no authMode field is configured
477  if (!isset($result['processedTca']['columns'][$fieldName]['config']['authMode'])
478  || !is_string($result['processedTca']['columns'][$fieldName]['config']['authMode'])
479  ) {
480  return $items;
481  }
482 
483  $backendUser = $this->‪getBackendUser();
484  foreach ($items as $key => $itemValues) {
485  if (!$backendUser->checkAuthMode($result['tableName'], $fieldName, $itemValues['value'])) {
486  unset($items[$key]);
487  }
488  }
489 
490  return $items;
491  }
492 
503  protected function ‪removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
504  {
505  $table = $result['tableName'];
506  $backendUser = $this->‪getBackendUser();
507  // Guard clause returns if not correct table and field or if user is admin
508  if ($table !== 'pages' || $fieldName !== 'doktype' || $backendUser->isAdmin()
509  ) {
510  return $items;
511  }
512 
513  $allowedPageTypes = $backendUser->groupData['pagetypes_select'];
514  foreach ($items as $key => $itemValues) {
515  if (!‪GeneralUtility::inList($allowedPageTypes, $itemValues['value'])) {
516  unset($items[$key]);
517  }
518  }
519 
520  return $items;
521  }
522 
533  protected function ‪removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
534  {
535  $referencedTableName = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'] ?? null;
536  if ($referencedTableName !== 'sys_file_storage') {
537  return $items;
538  }
539 
540  $allowedStorageIds = array_map(
541  static function (‪ResourceStorage $storage): int {
542  return $storage->‪getUid();
543  },
544  $this->‪getBackendUser()->getFileStorages()
545  );
546 
547  return array_filter(
548  $items,
549  static function (array $item) use ($allowedStorageIds): bool {
550  $itemValue = $item['value'] ?? null;
551  return empty($itemValue)
552  || in_array((int)$itemValue, $allowedStorageIds, true);
553  }
554  );
555  }
556 
566  protected function ‪buildForeignTableQueryBuilder(array $result, string $localFieldName, bool $selectAllFields = false): QueryBuilder
567  {
568  $backendUser = $this->‪getBackendUser();
569 
570  $foreignTableName = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table'];
571  $foreignTableClauseArray = $this->‪processForeignTableClause($result, $foreignTableName, $localFieldName);
572 
573  if ($selectAllFields) {
574  $fieldList = [$foreignTableName . '.*'];
575  } else {
576  $fieldList = BackendUtility::getCommonSelectFields($foreignTableName, $foreignTableName . '.');
577  $fieldList = GeneralUtility::trimExplode(',', $fieldList, true);
578  }
579 
580  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
581  ->getQueryBuilderForTable($foreignTableName);
582 
583  $queryBuilder->getRestrictions()
584  ->removeAll()
585  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
586  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->‪getBackendUser()->workspace));
587 
588  $queryBuilder
589  ->select(...$fieldList)
590  ->from($foreignTableName)
591  ->where($foreignTableClauseArray['WHERE']);
592 
593  if (!empty($foreignTableClauseArray['GROUPBY'])) {
594  $queryBuilder->groupBy(...$foreignTableClauseArray['GROUPBY']);
595  }
596 
597  if (!empty($foreignTableClauseArray['ORDERBY'])) {
598  foreach ($foreignTableClauseArray['ORDERBY'] as $orderPair) {
599  [$fieldName, $order] = $orderPair;
600  $queryBuilder->addOrderBy($fieldName, $order);
601  }
602  } elseif (!empty(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby'])) {
603  $orderByClauses = ‪QueryHelper::parseOrderBy(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby']);
604  foreach ($orderByClauses as $orderByClause) {
605  if (!empty($orderByClause[0])) {
606  $queryBuilder->addOrderBy($foreignTableName . '.' . $orderByClause[0], $orderByClause[1]);
607  }
608  }
609  }
610 
611  if (!empty($foreignTableClauseArray['LIMIT'])) {
612  if (!empty($foreignTableClauseArray['LIMIT'][1])) {
613  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][1]);
614  $queryBuilder->setFirstResult($foreignTableClauseArray['LIMIT'][0]);
615  } elseif (!empty($foreignTableClauseArray['LIMIT'][0])) {
616  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][0]);
617  }
618  }
619 
620  // rootLevel = -1 means that elements can be on the rootlevel OR on any page (pid!=-1)
621  // rootLevel = 0 means that elements are not allowed on root level
622  // rootLevel = 1 means that elements are only on the root level (pid=0)
623  $rootLevel = 0;
624  if (isset(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'])) {
625  $rootLevel = (int)‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'];
626  }
627 
628  if ($rootLevel === -1) {
629  $queryBuilder->andWhere(
630  $queryBuilder->expr()->neq(
631  $foreignTableName . '.pid',
632  $queryBuilder->createNamedParameter(-1, ‪Connection::PARAM_INT)
633  )
634  );
635  } elseif ($rootLevel === 1) {
636  $queryBuilder->andWhere(
637  $queryBuilder->expr()->eq(
638  $foreignTableName . '.pid',
639  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
640  )
641  );
642  } else {
643  $queryBuilder->andWhere($backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
644  if ($foreignTableName !== 'pages') {
645  $queryBuilder
646  ->from('pages')
647  ->andWhere(
648  $queryBuilder->expr()->eq(
649  'pages.uid',
650  $queryBuilder->quoteIdentifier($foreignTableName . '.pid')
651  )
652  );
653  }
654  }
655 
656  // @todo what about PID restriction?
657  if ($this->‪getBackendUser()->workspace !== 0 && BackendUtility::isTableWorkspaceEnabled($foreignTableName)) {
658  $queryBuilder
659  ->andWhere(
660  $queryBuilder->expr()->neq(
661  $foreignTableName . '.t3ver_state',
662  $queryBuilder->createNamedParameter(VersionState::MOVE_POINTER->value, ‪Connection::PARAM_INT)
663  )
664  );
665  }
666 
667  return $queryBuilder;
668  }
669 
686  protected function ‪processForeignTableClause(array $result, $foreignTableName, $localFieldName)
687  {
688  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($foreignTableName);
689  $localTable = $result['tableName'];
690  $effectivePid = $result['effectivePid'];
691 
692  $foreignTableClause = '';
693  if (!empty($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
694  && is_string($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
695  ) {
696  $foreignTableClause = ‪QueryHelper::quoteDatabaseIdentifiers($connection, $result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where']);
697  // Replace possible markers in query
698  if (str_contains($foreignTableClause, '###REC_FIELD_')) {
699  // " AND table.field='###REC_FIELD_field1###' AND ..." -> array(" AND table.field='", "field1###' AND ...")
700  $whereClauseParts = explode('###REC_FIELD_', $foreignTableClause);
701  foreach ($whereClauseParts as $key => $value) {
702  if ($key !== 0) {
703  // "field1###' AND ..." -> array("field1", "' AND ...")
704  $whereClauseSubParts = explode('###', $value, 2);
705  // @todo: Throw exception if there is no value? What happens for NEW records?
706  $databaseRowKey = empty($result['flexParentDatabaseRow']) ? 'databaseRow' : 'flexParentDatabaseRow';
707  $rowFieldValue = $result[$databaseRowKey][$whereClauseSubParts[0]] ?? '';
708  if (is_array($rowFieldValue)) {
709  // If a select or group field is used here, it may have been processed already and
710  // is now an array containing uid + table + title + row.
711  // See TcaGroup data provider for details.
712  // Pick the first one (always on 0), and use uid only.
713  $rowFieldValue = $rowFieldValue[0]['uid'] ?? $rowFieldValue[0] ?? '';
714  }
715  if (str_ends_with($whereClauseParts[0], '\'') && $whereClauseSubParts[1][0] === '\'') {
716  $whereClauseParts[0] = substr($whereClauseParts[0], 0, -1);
717  $whereClauseSubParts[1] = substr($whereClauseSubParts[1], 1);
718  }
719  $whereClauseParts[$key] = $connection->quote($rowFieldValue) . $whereClauseSubParts[1];
720  }
721  }
722  $foreignTableClause = implode('', $whereClauseParts);
723  }
724  if (str_contains($foreignTableClause, '###CURRENT_PID###')) {
725  // Use pid from parent page clause if in flex form context
726  if (!empty($result['flexParentDatabaseRow']['pid'])) {
727  $effectivePid = $result['flexParentDatabaseRow']['pid'];
728  } elseif (!$effectivePid && !empty($result['databaseRow']['pid'])) {
729  // Use pid from database row if in inline context
730  $effectivePid = $result['databaseRow']['pid'];
731  }
732  }
733 
734  $siteRootUid = 0;
735  foreach ($result['rootline'] as $rootlinePage) {
736  if (!empty($rootlinePage['is_siteroot'])) {
737  $siteRootUid = (int)$rootlinePage['uid'];
738  break;
739  }
740  }
741 
742  $pageTsConfigId = 0;
743  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'])
744  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID']
745  ) {
746  $pageTsConfigId = (int)$result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'];
747  }
748 
749  $pageTsConfigIdList = 0;
750  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'])
751  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST']
752  ) {
753  $pageTsConfigIdList = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'];
754  }
755  $pageTsConfigIdListArray = GeneralUtility::trimExplode(',', $pageTsConfigIdList, true);
756  $pageTsConfigIdList = [];
757  foreach ($pageTsConfigIdListArray as $pageTsConfigIdListElement) {
758  if (‪MathUtility::canBeInterpretedAsInteger($pageTsConfigIdListElement)) {
759  $pageTsConfigIdList[] = (int)$pageTsConfigIdListElement;
760  }
761  }
762  $pageTsConfigIdList = implode(',', $pageTsConfigIdList);
763 
764  $pageTsConfigString = '';
765  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'])
766  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR']
767  ) {
768  $pageTsConfigString = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'];
769  $pageTsConfigString = $connection->quote($pageTsConfigString);
770  }
771 
772  $foreignTableClause = str_replace(
773  [
774  '###CURRENT_PID###',
775  '###THIS_UID###',
776  '###SITEROOT###',
777  '###PAGE_TSCONFIG_ID###',
778  '###PAGE_TSCONFIG_IDLIST###',
779  '\'###PAGE_TSCONFIG_STR###\'',
780  '###PAGE_TSCONFIG_STR###',
781  ],
782  [
783  (int)$effectivePid,
784  (int)$result['databaseRow']['uid'],
785  $siteRootUid,
786  $pageTsConfigId,
787  $pageTsConfigIdList,
788  $pageTsConfigString,
789  $pageTsConfigString,
790  ],
791  $foreignTableClause
792  );
793 
794  $parsedSiteConfiguration = $this->‪parseSiteConfiguration($result['site'], $foreignTableClause);
795  if ($parsedSiteConfiguration !== []) {
796  $parsedSiteConfiguration = $this->‪quoteParsedSiteConfiguration($connection, $parsedSiteConfiguration);
797  $foreignTableClause = $this->‪replaceParsedSiteConfiguration($foreignTableClause, $parsedSiteConfiguration);
798  }
799  }
800 
801  // Split the clause into an array with keys WHERE, GROUPBY, ORDERBY, LIMIT
802  // Prepend a space to make sure "[[:space:]]+" will find a space there for the first element.
803  $foreignTableClause = ' ' . $foreignTableClause;
804  $foreignTableClauseArray = [
805  'WHERE' => '',
806  'GROUPBY' => '',
807  'ORDERBY' => '',
808  'LIMIT' => '',
809  ];
810  // Find LIMIT
811  $reg = [];
812  if (preg_match('/^(.*)[[:space:]]+LIMIT[[:space:]]+([[:alnum:][:space:],._]+)$/is', $foreignTableClause, $reg)) {
813  $foreignTableClauseArray['LIMIT'] = GeneralUtility::intExplode(',', trim($reg[2]), true);
814  $foreignTableClause = $reg[1];
815  }
816  // Find ORDER BY
817  $reg = [];
818  if (preg_match('/^(.*)[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
819  $foreignTableClauseArray['ORDERBY'] = ‪QueryHelper::parseOrderBy(trim($reg[2]));
820  $foreignTableClause = $reg[1];
821  }
822  // Find GROUP BY
823  $reg = [];
824  if (preg_match('/^(.*)[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
825  $foreignTableClauseArray['GROUPBY'] = ‪QueryHelper::parseGroupBy(trim($reg[2]));
826  $foreignTableClause = $reg[1];
827  }
828  // Rest is assumed to be "WHERE" clause
829  $foreignTableClauseArray['WHERE'] = ‪QueryHelper::stripLogicalOperatorPrefix($foreignTableClause);
830 
831  return $foreignTableClauseArray;
832  }
833 
841  protected function ‪parseSiteConfiguration(?‪SiteInterface $site, string $input): array
842  {
843  // Since we need to access the configuration, early return in case
844  // we don't deal with an instance of Site (e.g. null or NullSite).
845  if (!$site instanceof ‪Site) {
846  return [];
847  }
848 
849  $siteClausesRegEx = '/###SITE:([^#]+)###/m';
850  preg_match_all($siteClausesRegEx, $input, $matches, PREG_SET_ORDER);
851 
852  if (empty($matches)) {
853  return [];
854  }
855 
856  $replacements = [];
857  $configuration = $site->getConfiguration();
858  array_walk($matches, static function (array $match) use (&$replacements, &$configuration): void {
859  $key = $match[1];
860  try {
861  $value = ‪ArrayUtility::getValueByPath($configuration, $key, '.');
862  } catch (‪MissingArrayPathException $exception) {
863  $value = '';
864  }
865 
866  $replacements[$match[0]] = $value;
867  });
868 
869  return $replacements;
870  }
871 
872  protected function ‪quoteParsedSiteConfiguration(‪Connection $connection, array $parsedSiteConfiguration): array
873  {
874  foreach ($parsedSiteConfiguration as $key => $value) {
875  if (is_int($value)) {
876  // int values are safe, nothing to do here
877  continue;
878  }
879  if (is_string($value)) {
880  $parsedSiteConfiguration[$key] = $connection->quote($value);
881  continue;
882  }
883  if (is_array($value)) {
884  $parsedSiteConfiguration[$key] = implode(',', $this->‪quoteParsedSiteConfiguration($connection, $value));
885  continue;
886  }
887  if (is_bool($value)) {
888  $parsedSiteConfiguration[$key] = (int)$value;
889  continue;
890  }
891  throw new \InvalidArgumentException(
892  sprintf('Cannot quote site configuration setting "%s" of type "%s", only "int", "bool", "string" and "array" are supported', $key, gettype($value)),
893  1630324435
894  );
895  }
896 
897  return $parsedSiteConfiguration;
898  }
899 
900  protected function ‪replaceParsedSiteConfiguration(string $input, array $parsedSiteConfiguration): string
901  {
902  return str_replace(
903  array_keys($parsedSiteConfiguration),
904  array_values($parsedSiteConfiguration),
905  $input
906  );
907  }
908 
912  protected function ‪parseStartingPointsFromSiteConfiguration(array $result, array $fieldConfig): array
913  {
914  if (!isset($fieldConfig['config']['treeConfig']['startingPoints'])) {
915  return $fieldConfig;
916  }
917 
918  $parsedSiteConfiguration = $this->‪parseSiteConfiguration($result['site'], $fieldConfig['config']['treeConfig']['startingPoints']);
919  if ($parsedSiteConfiguration !== []) {
920  // $this->quoteParsedSiteConfiguration() is omitted on purpose, all values are cast to integers
921  $parsedSiteConfiguration = array_unique(array_map(static function (array|string|int $value): string {
922  if (is_array($value)) {
923  return implode(',', array_map(intval(...), $value));
924  }
925 
926  return implode(',', GeneralUtility::intExplode(',', (string)$value, true));
927  }, $parsedSiteConfiguration));
928  $resolvedStartingPoints = $this->‪replaceParsedSiteConfiguration($fieldConfig['config']['treeConfig']['startingPoints'], $parsedSiteConfiguration);
929  // Add the resolved starting points while removing empty values
930  $fieldConfig['config']['treeConfig']['startingPoints'] = implode(
931  ',',
932  GeneralUtility::trimExplode(',', $resolvedStartingPoints, true)
933  );
934  }
935 
936  return $fieldConfig;
937  }
938 
946  protected function ‪processDatabaseFieldValue(array $row, $fieldName)
947  {
948  $currentDatabaseValues = array_key_exists($fieldName, $row)
949  ? $row[$fieldName]
950  : '';
951  if (!is_array($currentDatabaseValues)) {
952  $currentDatabaseValues = GeneralUtility::trimExplode(',', $currentDatabaseValues, true);
953  }
954  return $currentDatabaseValues;
955  }
956 
968  protected function ‪processSelectFieldValue(array $result, $fieldName, array $staticValues)
969  {
970  $fieldConfig = $result['processedTca']['columns'][$fieldName];
971 
972  $currentDatabaseValueArray = array_key_exists($fieldName, $result['databaseRow']) ? $result['databaseRow'][$fieldName] : [];
973  $newDatabaseValueArray = [];
974 
975  // Add all values that were defined by static methods and do not come from the relation
976  // e.g. TCA, TSconfig, itemProcFunc etc.
977  foreach ($currentDatabaseValueArray as $value) {
978  if (isset($staticValues[$value])) {
979  $newDatabaseValueArray[] = $value;
980  }
981  }
982 
983  if (isset($fieldConfig['config']['foreign_table']) && !empty($fieldConfig['config']['foreign_table'])) {
984  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
985  $relationHandler->registerNonTableValues = !empty($fieldConfig['config']['allowNonIdValues']);
986  if (!empty($fieldConfig['config']['MM']) && $result['command'] !== 'new') {
987  // MM relation
988  $relationHandler->start(
989  implode(',', $currentDatabaseValueArray),
990  $fieldConfig['config']['foreign_table'],
991  $fieldConfig['config']['MM'],
992  $result['databaseRow']['uid'],
993  $result['tableName'],
994  $fieldConfig['config']
995  );
996  $relationHandler->processDeletePlaceholder();
997  $newDatabaseValueArray = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
998  } else {
999  // Non MM relation
1000  // If not dealing with MM relations, use default live uid, not versioned uid for record relations
1001  $relationHandler->start(
1002  implode(',', $currentDatabaseValueArray),
1003  $fieldConfig['config']['foreign_table'],
1004  '',
1005  $this->‪getLiveUid($result),
1006  $result['tableName'],
1007  $fieldConfig['config']
1008  );
1009  $relationHandler->processDeletePlaceholder();
1010  $databaseIds = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
1011  // remove all items from the current DB values if not available as relation or static value anymore
1012  $newDatabaseValueArray = array_values(array_intersect($currentDatabaseValueArray, $databaseIds));
1013  }
1014  }
1015 
1016  if ($fieldConfig['config']['multiple'] ?? false) {
1017  return $newDatabaseValueArray;
1018  }
1019  return array_unique($newDatabaseValueArray);
1020  }
1021 
1033  public function ‪translateLabels(array $result, array $itemArray, $table, $fieldName)
1034  {
1035  $languageService = $this->‪getLanguageService();
1036 
1037  foreach ($itemArray as $key => $item) {
1038  $labelIndex = $item['value'] ?? '';
1039 
1040  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex])
1041  && !empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex])
1042  ) {
1043  $label = $languageService->sL($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex]);
1044  } else {
1045  $label = $languageService->sL(trim($item['label'] ?? ''));
1046  }
1047  $value = strlen((string)($item['value'] ?? '')) > 0 ? $item['value'] : '';
1048  $icon = !empty($item['icon']) ? $item['icon'] : null;
1049  $groupId = $item['group'] ?? null;
1050  $helpText = null;
1051  if (!empty($item['description'])) {
1052  if (is_string($item['description'])) {
1053  $helpText = $languageService->sL($item['description']);
1054  } else {
1055  $helpText = $item['description'];
1056  }
1057  }
1058  $itemArray[$key] = [
1059  'label' => $label,
1060  'value' => $value,
1061  'icon' => $icon,
1062  'group' => $groupId,
1063  'description' => $helpText,
1064  ];
1065  }
1066 
1067  return $itemArray;
1068  }
1069 
1073  public function ‪addIconFromAltIcons(array $result, array $items, string $table, string $fieldName): array
1074  {
1075  foreach ($items as &$item) {
1076  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item['value']])
1077  && !empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item['value']])
1078  ) {
1079  $item['icon'] = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item['value']];
1080  }
1081  }
1082 
1083  return $items;
1084  }
1085 
1097  public function ‪sanitizeItemArray($itemArray, $tableName, $fieldName)
1098  {
1099  if (!is_array($itemArray)) {
1100  $itemArray = [];
1101  }
1102  foreach ($itemArray as $item) {
1103  if (!is_array($item)) {
1104  throw new \UnexpectedValueException(
1105  'An item in field ' . $fieldName . ' of table ' . $tableName . ' is not an array as expected',
1106  1439288036
1107  );
1108  }
1109  }
1110 
1111  return $itemArray;
1112  }
1113 
1122  protected function ‪getLiveUid(array $result)
1123  {
1124  $table = $result['tableName'];
1125  $row = $result['databaseRow'];
1126  ‪$uid = $row['uid'] ?? 0;
1127  if (BackendUtility::isTableWorkspaceEnabled($table) && (int)($row['t3ver_oid'] ?? 0) > 0) {
1128  ‪$uid = $row['t3ver_oid'];
1129  }
1130  return ‪$uid;
1131  }
1132 
1134  {
1135  return ‪$GLOBALS['LANG'];
1136  }
1137 
1139  {
1140  return ‪$GLOBALS['BE_USER'];
1141  }
1142 }
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\sanitizeItemArray
‪array sanitizeItemArray($itemArray, $tableName, $fieldName)
Definition: AbstractItemProvider.php:1097
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromPageTsConfig
‪array addItemsFromPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:146
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\replaceParsedSiteConfiguration
‪replaceParsedSiteConfiguration(string $input, array $parsedSiteConfiguration)
Definition: AbstractItemProvider.php:900
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:50
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:337
‪TYPO3\CMS\Core\Database\Query\QueryHelper\quoteDatabaseIdentifiers
‪static quoteDatabaseIdentifiers(Connection $connection, string $sql)
Definition: QueryHelper.php:224
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserLanguageFieldRestriction
‪array removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:445
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:36
‪TYPO3\CMS\Core\Versioning\VersionState
‪VersionState
Definition: VersionState.php:22
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:27
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addIconFromAltIcons
‪addIconFromAltIcons(array $result, array $items, string $table, string $fieldName)
Definition: AbstractItemProvider.php:1073
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseGroupBy
‪static array string[] parseGroupBy(string $input)
Definition: QueryHelper.php:102
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\translateLabels
‪array translateLabels(array $result, array $itemArray, $table, $fieldName)
Definition: AbstractItemProvider.php:1033
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromForeignTable
‪array addItemsFromForeignTable(array $result, $fieldName, array $items, bool $includeFullRows=false)
Definition: AbstractItemProvider.php:265
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static getValueByPath(array $array, array|string $path, string $delimiter='/')
Definition: ArrayUtility.php:176
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getBackendUser
‪getBackendUser()
Definition: AbstractItemProvider.php:1138
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger(mixed $var)
Definition: MathUtility.php:69
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\parseStartingPointsFromSiteConfiguration
‪parseStartingPointsFromSiteConfiguration(array $result, array $fieldConfig)
Definition: AbstractItemProvider.php:912
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processForeignTableClause
‪array processForeignTableClause(array $result, $foreignTableName, $localFieldName)
Definition: AbstractItemProvider.php:686
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLiveUid
‪int string getLiveUid(array $result)
Definition: AbstractItemProvider.php:1122
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Resource\FileRepository
Definition: FileRepository.php:38
‪TYPO3\CMS\Backend\Form\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Schema\Struct\SelectItem
Definition: SelectItem.php:21
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserStorageRestriction
‪array removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:533
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\resolveItemProcessorFunction
‪array resolveItemProcessorFunction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:59
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByDoktypeUserRestriction
‪array removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:503
‪TYPO3\CMS\Core\Schema\Struct\SelectItem\fromTcaItemArray
‪static fromTcaItemArray(array $item, string $type='select')
Definition: SelectItem.php:45
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:60
‪TYPO3\CMS\Core\Type\Bitmask\Permission\PAGE_SHOW
‪const PAGE_SHOW
Definition: Permission.php:35
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\parseSiteConfiguration
‪parseSiteConfiguration(?SiteInterface $site, string $input)
Definition: AbstractItemProvider.php:841
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:16
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLanguageService
‪getLanguageService()
Definition: AbstractItemProvider.php:1133
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByKeepItemsPageTsConfig
‪array removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:378
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processDatabaseFieldValue
‪array processDatabaseFieldValue(array $row, $fieldName)
Definition: AbstractItemProvider.php:946
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:39
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\quoteParsedSiteConfiguration
‪quoteParsedSiteConfiguration(Connection $connection, array $parsedSiteConfiguration)
Definition: AbstractItemProvider.php:872
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:128
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:27
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processSelectFieldValue
‪array processSelectFieldValue(array $result, $fieldName, array $staticValues)
Definition: AbstractItemProvider.php:968
‪TYPO3\CMS\Webhooks\Message\$uid
‪identifier readonly int $uid
Definition: PageModificationMessage.php:35
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:171
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:26
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:24
‪TYPO3\CMS\Core\Utility\GeneralUtility\inList
‪static bool inList($list, $item)
Definition: GeneralUtility.php:421
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserAuthMode
‪array removeItemsByUserAuthMode(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:474
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:48
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange(mixed $theInt, int $min, int $max=2000000000, int $defaultValue=0)
Definition: MathUtility.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:51
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromFolder
‪array addItemsFromFolder(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:193
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider
Definition: AbstractItemProvider.php:50
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByRemoveItemsPageTsConfig
‪array removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:411
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\buildForeignTableQueryBuilder
‪buildForeignTableQueryBuilder(array $result, string $localFieldName, bool $selectAllFields=false)
Definition: AbstractItemProvider.php:566
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:39