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