‪TYPO3CMS  11.5
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;
24 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  GeneralUtility::callUserFunction($config['itemsProcFunc'], $processorParameters, $this);
98  } catch (\‪Exception $exception) {
99  // The itemsProcFunc method may throw an exception, create a flash message if so
100  $languageService = $this->‪getLanguageService();
101  $fieldLabel = $fieldName;
102  if (!empty($result['processedTca']['columns'][$fieldName]['label'])) {
103  $fieldLabel = $languageService->sL($result['processedTca']['columns'][$fieldName]['label']);
104  }
105  $message = sprintf(
106  $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.items_proc_func_error'),
107  $fieldLabel,
108  $exception->getMessage()
109  );
110  $flashMessage = GeneralUtility::makeInstance(
111  FlashMessage::class,
112  $message,
113  '',
115  true
116  );
117  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
118  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
119  $defaultFlashMessageQueue->enqueue($flashMessage);
120  }
121 
122  return $items;
123  }
124 
138  protected function ‪addItemsFromPageTsConfig(array $result, $fieldName, array $items)
139  {
140  $table = $result['tableName'];
141  if (!empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
142  && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'])
143  ) {
144  $addItemsArray = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['addItems.'];
145  foreach ($addItemsArray as $value => $label) {
146  // If the value ends with a dot, it is a subelement like "34.icon = mylabel.png", skip it
147  if (substr($value, -1) === '.') {
148  continue;
149  }
150  // Check if value "34 = mylabel" also has a "34.icon = myImage.png"
151  $iconIdentifier = null;
152  if (isset($addItemsArray[$value . '.'])
153  && is_array($addItemsArray[$value . '.'])
154  && !empty($addItemsArray[$value . '.']['icon'])
155  ) {
156  $iconIdentifier = $addItemsArray[$value . '.']['icon'];
157  }
158  $items[] = [$label, $value, $iconIdentifier];
159  }
160  }
161  return $items;
162  }
163 
176  protected function ‪addItemsFromSpecial(array $result, $fieldName, array $items)
177  {
178  // Guard
179  if (empty($result['processedTca']['columns'][$fieldName]['config']['special'])
180  || !is_string($result['processedTca']['columns'][$fieldName]['config']['special'])
181  ) {
182  return $items;
183  }
184 
185  $special = $result['processedTca']['columns'][$fieldName]['config']['special'];
186 
187  trigger_error(
188  'Using the TCA property \'special=' . $special . '\' is deprecated and will be removed in ‪TYPO3 v12. Use a custom itemsProcFunc instead.',
189  E_USER_DEPRECATED
190  );
191 
192  switch (true) {
193  case $special === 'tables':
194  $fieldInformation = ['items' => $items];
195  (new TcaItemsProcessorFunctions())->populateAvailableTables($fieldInformation);
196  $items = $fieldInformation['items'];
197  break;
198  case $special === 'pagetypes':
199  $fieldInformation = ['items' => $items];
200  (new TcaItemsProcessorFunctions())->populateAvailablePageTypes($fieldInformation);
201  $items = $fieldInformation['items'];
202  break;
203  case $special === 'exclude':
204  $fieldInformation = ['items' => $items];
205  (new TcaItemsProcessorFunctions())->populateExcludeFields($fieldInformation);
206  $items = $fieldInformation['items'];
207  break;
208  case $special === 'explicitValues':
209  $fieldInformation = ['items' => $items];
210  (new TcaItemsProcessorFunctions())->populateExplicitAuthValues($fieldInformation);
211  $items = $fieldInformation['items'];
212  break;
213  case $special === 'custom':
214  $fieldInformation = ['items' => $items];
215  (new TcaItemsProcessorFunctions())->populateCustomPermissionOptions($fieldInformation);
216  $items = $fieldInformation['items'];
217  break;
218  case $special === 'modListGroup':
219  $fieldInformation = ['items' => $items];
220  (new TcaItemsProcessorFunctions())->populateAvailableGroupModules($fieldInformation);
221  $items = $fieldInformation['items'];
222  break;
223  case $special === 'modListUser':
224  $fieldInformation = ['items' => $items];
225  (new TcaItemsProcessorFunctions())->populateAvailableUserModules($fieldInformation);
226  $items = $fieldInformation['items'];
227  break;
228  default:
229  throw new \UnexpectedValueException(
230  'Unknown special value ' . $special . ' for field ' . $fieldName . ' of table ' . $result['tableName'],
231  1439298496
232  );
233  }
234  return $items;
235  }
236 
248  protected function addItemsFromFolder(array $result, $fieldName, array $items)
249  {
250  if (empty($result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig']['folder'])
251  || !is_string($result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig']['folder'])
252  ) {
253  return $items;
254  }
255 
256  $tableName = $result['tableName'];
257  $fileFolderConfig = $result['processedTca']['columns'][$fieldName]['config']['fileFolderConfig'];
258  $fileFolderTSconfig = $result['pageTsConfig']['TCEFORM.'][$tableName . '.'][$fieldName . '.']['config.']['fileFolderConfig.'] ?? [];
259 
260  if (is_array($fileFolderTSconfig) && $fileFolderTSconfig !== []) {
261  if ($fileFolderTSconfig['folder'] ?? false) {
262  $fileFolderConfig['folder'] = $fileFolderTSconfig['folder'];
263  }
264  if (isset($fileFolderTSconfig['allowedExtensions'])) {
265  $fileFolderConfig['allowedExtensions'] = $fileFolderTSconfig['allowedExtensions'];
266  }
267  if (isset($fileFolderTSconfig['depth'])) {
268  $fileFolderConfig['depth'] = (int)$fileFolderTSconfig['depth'];
269  }
270  }
271 
272  $folderRaw = $fileFolderConfig['folder'];
273  $folder = GeneralUtility::getFileAbsFileName($folderRaw);
274  if ($folder === '') {
275  throw new \RuntimeException(
276  'Invalid folder given for item processing: ' . $folderRaw . ' for table ' . $tableName . ', field ' . $fieldName,
277  1479399227
278  );
279  }
280  $folder = rtrim($folder, '/') . '/';
281 
282  if (@is_dir($folder)) {
283  $allowedExtensions = '';
284  if (!empty($fileFolderConfig['allowedExtensions']) && is_string($fileFolderConfig['allowedExtensions'])) {
285  $allowedExtensions = $fileFolderConfig['allowedExtensions'];
286  }
287  $depth = isset($fileFolderConfig['depth'])
288  ? MathUtility::forceIntegerInRange($fileFolderConfig['depth'], 0, 99)
289  : 99;
290  $fileArray = GeneralUtility::getAllFilesAndFoldersInPath([], $folder, $allowedExtensions, false, $depth);
291  $fileArray = GeneralUtility::removePrefixPathFromList($fileArray, $folder);
292  foreach ($fileArray as $fileReference) {
293  $fileInformation = pathinfo($fileReference);
294  $icon = GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], strtolower($fileInformation['extension']))
295  ? $folder . $fileReference
296  : '';
297  $items[] = [
298  $fileReference,
299  $fileReference,
300  $icon,
301  ];
302  }
303  }
304 
305  return $items;
306  }
307 
320  protected function addItemsFromForeignTable(array $result, $fieldName, array $items, bool $includeFullRows = false)
321  {
322  $databaseError = null;
323  $queryResult = null;
324  // Guard
325  if (empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
326  || !is_string($result['processedTca']['columns'][$fieldName]['config']['foreign_table'])
327  ) {
328  return $items;
329  }
330 
331  $languageService = $this->getLanguageService();
332 
333  $foreignTable = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'];
334 
335  if (!isset($GLOBALS['TCA'][$foreignTable]) || !is_array($GLOBALS['TCA'][$foreignTable])) {
336  throw new \UnexpectedValueException(
337  'Field ' . $fieldName . ' of table ' . $result['tableName'] . ' reference to foreign table '
338  . $foreignTable . ', but this table is not defined in TCA',
339  1439569743
340  );
341  }
342 
343  $queryBuilder = $this->buildForeignTableQueryBuilder($result, $fieldName, $includeFullRows);
344  try {
345  $queryResult = $queryBuilder->executeQuery();
346  } catch (DBALException $e) {
347  $databaseError = $e->getPrevious()->getMessage();
348  }
349 
350  // Early return on error with flash message
351  if (!empty($databaseError)) {
352  $msg = $databaseError . '. ';
353  $msg .= $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch');
354  $msgTitle = $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:error.database_schema_mismatch_title');
355  $flashMessage = GeneralUtility::makeInstance(FlashMessage::class, $msg, $msgTitle, FlashMessage::ERROR, true);
356  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
357  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
358  $defaultFlashMessageQueue->enqueue($flashMessage);
359  return $items;
360  }
361 
362  $labelPrefix = '';
363  if (!empty($result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'])) {
364  $labelPrefix = $result['processedTca']['columns'][$fieldName]['config']['foreign_table_prefix'];
365  $labelPrefix = $languageService->sL($labelPrefix);
366  }
367 
368  $fileRepository = GeneralUtility::makeInstance(FileRepository::class);
369  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
370 
371  $allForeignRows = $queryResult->fetchAllAssociative();
372  // Find all possible versioned records of the current IDs, so we do not need to overlay each record
373  // This way, workspaceOL() does not need to be called for each record.
374  $workspaceId = $this->getBackendUser()->workspace;
375  $doOverlaysForRecords = BackendUtility::getPossibleWorkspaceVersionIdsOfLiveRecordIds($foreignTable, array_column($allForeignRows, 'uid'), $workspaceId);
376 
377  foreach ($allForeignRows as $foreignRow) {
378  // Only do workspace overlays when a versioned record exists.
379  if (isset($foreignRow['uid']) && isset($doOverlaysForRecords[(int)$foreignRow['uid']])) {
380  BackendUtility::workspaceOL($foreignTable, $foreignRow, $workspaceId);
381  }
382  // Only proceed in case the row was not unset and we don't deal with a delete placeholder
383  ‪if (is_array($foreignRow)
384  && !‪VersionState::cast($foreignRow['t3ver_state'] ?? 0)->equals(‪VersionState::DELETE_PLACEHOLDER)
385  ) {
386  // If the foreign table sets selicon_field, this field can contain an image
387  // that represents this specific row.
388  $iconFieldName = '';
389  $isReferenceField = false;
390  if (!empty(‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'])) {
391  $iconFieldName = ‪$GLOBALS['TCA'][$foreignTable]['ctrl']['selicon_field'];
392  if (isset(‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['type'])
393  && ‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['type'] === 'inline'
394  && ‪$GLOBALS['TCA'][$foreignTable]['columns'][$iconFieldName]['config']['foreign_table'] === 'sys_file_reference'
395  ) {
396  $isReferenceField = true;
397  }
398  }
399  $icon = '';
400  if ($isReferenceField) {
401  $references = $fileRepository->findByRelation($foreignTable, $iconFieldName, $foreignRow['uid']);
402  if (is_array($references) && !empty($references)) {
403  $icon = reset($references);
404  $icon = $icon->getPublicUrl();
405  }
406  } else {
407  // Else, determine icon based on record type, or a generic fallback
408  $icon = $iconFactory->mapRecordTypeToIconIdentifier($foreignTable, $foreignRow);
409  }
410  $item = [
411  0 => $labelPrefix . BackendUtility::getRecordTitle($foreignTable, $foreignRow),
412  1 => $foreignRow['uid'],
413  2 => $icon,
414  ];
415  if ($includeFullRows) {
416  // @todo: This is part of the category tree performance hack
417  $item['_row'] = $foreignRow;
418  }
419  $items[] = $item;
420  }
421  }
422 
423  return $items;
424  }
425 
436  protected function ‪removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
437  {
438  $table = $result['tableName'];
439  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
440  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])
441  ) {
442  return $items;
443  }
444 
445  // If keepItems is set but is an empty list all current items get removed
446  if ($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'] === '') {
447  return [];
448  }
449 
451  $items,
452  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'],
453  static function ($value) {
454  return $value[1];
455  }
456  );
457  }
458 
469  protected function ‪removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
470  {
471  $table = $result['tableName'];
472  if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
473  || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'])
474  || $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'] === ''
475  ) {
476  return $items;
477  }
478 
479  $removeItems = array_flip(‪GeneralUtility::trimExplode(
480  ',',
481  $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['removeItems'],
482  true
483  ));
484  foreach ($items as $key => $itemValues) {
485  if (isset($removeItems[$itemValues[1]])) {
486  unset($items[$key]);
487  }
488  }
489 
490  return $items;
491  }
492 
503  protected function ‪removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
504  {
505  // Guard clause returns if not a language field is handled
506  if (empty($result['processedTca']['ctrl']['languageField'])
507  || $result['processedTca']['ctrl']['languageField'] !== $fieldName
508  ) {
509  return $items;
510  }
511 
512  $backendUser = $this->getBackendUser();
513  foreach ($items as $key => $itemValues) {
514  if (!$backendUser->checkLanguageAccess($itemValues[1])) {
515  unset($items[$key]);
516  }
517  }
518 
519  return $items;
520  }
521 
532  protected function ‪removeItemsByUserAuthMode(array $result, $fieldName, array $items)
533  {
534  // Guard clause returns early if no authMode field is configured
535  if (!isset($result['processedTca']['columns'][$fieldName]['config']['authMode'])
536  || !is_string($result['processedTca']['columns'][$fieldName]['config']['authMode'])
537  ) {
538  return $items;
539  }
540 
541  $backendUser = $this->getBackendUser();
542  $authMode = $result['processedTca']['columns'][$fieldName]['config']['authMode'];
543  foreach ($items as $key => $itemValues) {
544  // @todo: checkAuthMode() uses $GLOBAL access for "individual" authMode - get rid of this
545  if (!$backendUser->checkAuthMode($result['tableName'], $fieldName, $itemValues[1], $authMode)) {
546  unset($items[$key]);
547  }
548  }
549 
550  return $items;
551  }
552 
563  protected function ‪removeItemsByDoktypeUserRestriction(array $result, $fieldName, array $items)
564  {
565  $table = $result['tableName'];
566  $backendUser = $this->getBackendUser();
567  // Guard clause returns if not correct table and field or if user is admin
568  if ($table !== 'pages' || $fieldName !== 'doktype' || $backendUser->isAdmin()
569  ) {
570  return $items;
571  }
572 
573  $allowedPageTypes = $backendUser->groupData['pagetypes_select'];
574  foreach ($items as $key => $itemValues) {
575  if (!GeneralUtility::inList($allowedPageTypes, $itemValues[1])) {
576  unset($items[$key]);
577  }
578  }
579 
580  return $items;
581  }
582 
593  protected function ‪removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
594  {
595  $referencedTableName = $result['processedTca']['columns'][$fieldName]['config']['foreign_table'] ?? null;
596  if ($referencedTableName !== 'sys_file_storage') {
597  return $items;
598  }
599 
600  $allowedStorageIds = array_map(
601  static function (‪ResourceStorage $storage) {
602  return $storage->‪getUid();
603  },
604  $this->getBackendUser()->getFileStorages()
605  );
606 
607  return array_filter(
608  $items,
609  static function (array $item) use ($allowedStorageIds) {
610  $itemValue = $item[1] ?? null;
611  return empty($itemValue)
612  || in_array((int)$itemValue, $allowedStorageIds, true);
613  }
614  );
615  }
616 
626  protected function ‪buildForeignTableQueryBuilder(array $result, string $localFieldName, bool $selectAllFields = false): QueryBuilder
627  {
628  $backendUser = $this->getBackendUser();
629 
630  $foreignTableName = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table'];
631  $foreignTableClauseArray = $this->processForeignTableClause($result, $foreignTableName, $localFieldName);
632 
633  if ($selectAllFields) {
634  $fieldList = [$foreignTableName . '.*'];
635  } else {
636  $fieldList = BackendUtility::getCommonSelectFields($foreignTableName, $foreignTableName . '.');
637  $fieldList = ‪GeneralUtility::trimExplode(',', $fieldList, true);
638  }
639 
640  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
641  ->getQueryBuilderForTable($foreignTableName);
642 
643  $queryBuilder->getRestrictions()
644  ->removeAll()
645  ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
646  ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->getBackendUser()->workspace));
647 
648  $queryBuilder
649  ->select(...$fieldList)
650  ->from($foreignTableName)
651  ->where($foreignTableClauseArray['WHERE']);
652 
653  if (!empty($foreignTableClauseArray['GROUPBY'])) {
654  $queryBuilder->groupBy(...$foreignTableClauseArray['GROUPBY']);
655  }
656 
657  if (!empty($foreignTableClauseArray['ORDERBY'])) {
658  foreach ($foreignTableClauseArray['ORDERBY'] as $orderPair) {
659  [$fieldName, $order] = $orderPair;
660  $queryBuilder->addOrderBy($fieldName, $order);
661  }
662  } elseif (!empty(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby'])) {
663  $orderByClauses = ‪QueryHelper::parseOrderBy(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['default_sortby']);
664  foreach ($orderByClauses as $orderByClause) {
665  if (!empty($orderByClause[0])) {
666  $queryBuilder->addOrderBy($foreignTableName . '.' . $orderByClause[0], $orderByClause[1]);
667  }
668  }
669  }
670 
671  if (!empty($foreignTableClauseArray['LIMIT'])) {
672  if (!empty($foreignTableClauseArray['LIMIT'][1])) {
673  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][1]);
674  $queryBuilder->setFirstResult($foreignTableClauseArray['LIMIT'][0]);
675  } elseif (!empty($foreignTableClauseArray['LIMIT'][0])) {
676  $queryBuilder->setMaxResults($foreignTableClauseArray['LIMIT'][0]);
677  }
678  }
679 
680  // rootLevel = -1 means that elements can be on the rootlevel OR on any page (pid!=-1)
681  // rootLevel = 0 means that elements are not allowed on root level
682  // rootLevel = 1 means that elements are only on the root level (pid=0)
683  $rootLevel = 0;
684  if (isset(‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'])) {
685  $rootLevel = (int)‪$GLOBALS['TCA'][$foreignTableName]['ctrl']['rootLevel'];
686  }
687 
688  if ($rootLevel === -1) {
689  $queryBuilder->andWhere(
690  $queryBuilder->expr()->neq(
691  $foreignTableName . '.pid',
692  $queryBuilder->createNamedParameter(-1, ‪Connection::PARAM_INT)
693  )
694  );
695  } elseif ($rootLevel === 1) {
696  $queryBuilder->andWhere(
697  $queryBuilder->expr()->eq(
698  $foreignTableName . '.pid',
699  $queryBuilder->createNamedParameter(0, ‪Connection::PARAM_INT)
700  )
701  );
702  } else {
703  $queryBuilder->andWhere($backendUser->getPagePermsClause(‪Permission::PAGE_SHOW));
704  if ($foreignTableName !== 'pages') {
705  $queryBuilder
706  ->from('pages')
707  ->andWhere(
708  $queryBuilder->expr()->eq(
709  'pages.uid',
710  $queryBuilder->quoteIdentifier($foreignTableName . '.pid')
711  )
712  );
713  }
714  }
715 
716  // @todo what about PID restriction?
717  if ($this->getBackendUser()->workspace !== 0 && BackendUtility::isTableWorkspaceEnabled($foreignTableName)) {
718  $queryBuilder
719  ->andWhere(
720  $queryBuilder->expr()->neq(
721  $foreignTableName . '.t3ver_state',
722  $queryBuilder->createNamedParameter(‪VersionState::MOVE_POINTER, ‪Connection::PARAM_INT)
723  )
724  );
725  }
726 
727  return $queryBuilder;
728  }
729 
746  protected function ‪processForeignTableClause(array $result, $foreignTableName, $localFieldName)
747  {
748  $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($foreignTableName);
749  $localTable = $result['tableName'];
750  $effectivePid = $result['effectivePid'];
751 
752  $foreignTableClause = '';
753  if (!empty($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
754  && is_string($result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'])
755  ) {
756  if (GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('runtimeDbQuotingOfTcaConfiguration')) {
757  $foreignTableClause = ‪QueryHelper::quoteDatabaseIdentifiers($connection, $result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where']);
758  } else {
759  $foreignTableClause = $result['processedTca']['columns'][$localFieldName]['config']['foreign_table_where'];
760  }
761  // Replace possible markers in query
762  if (str_contains($foreignTableClause, '###REC_FIELD_')) {
763  // " AND table.field='###REC_FIELD_field1###' AND ..." -> array(" AND table.field='", "field1###' AND ...")
764  $whereClauseParts = explode('###REC_FIELD_', $foreignTableClause);
765  foreach ($whereClauseParts as $key => $value) {
766  if ($key !== 0) {
767  // "field1###' AND ..." -> array("field1", "' AND ...")
768  $whereClauseSubParts = explode('###', $value, 2);
769  // @todo: Throw exception if there is no value? What happens for NEW records?
770  $databaseRowKey = empty($result['flexParentDatabaseRow']) ? 'databaseRow' : 'flexParentDatabaseRow';
771  $rowFieldValue = $result[$databaseRowKey][$whereClauseSubParts[0]] ?? '';
772  if (is_array($rowFieldValue)) {
773  // If a select or group field is used here, it may have been processed already and
774  // is now an array containing uid + table + title + row.
775  // See TcaGroup data provider for details.
776  // Pick the first one (always on 0), and use uid only.
777  $rowFieldValue = $rowFieldValue[0]['uid'] ?? $rowFieldValue[0] ?? '';
778  }
779  if (substr($whereClauseParts[0], -1) === '\'' && $whereClauseSubParts[1][0] === '\'') {
780  $whereClauseParts[0] = substr($whereClauseParts[0], 0, -1);
781  $whereClauseSubParts[1] = substr($whereClauseSubParts[1], 1);
782  }
783  $whereClauseParts[$key] = $connection->quote($rowFieldValue) . $whereClauseSubParts[1];
784  }
785  }
786  $foreignTableClause = implode('', $whereClauseParts);
787  }
788  if (str_contains($foreignTableClause, '###CURRENT_PID###')) {
789  // Use pid from parent page clause if in flex form context
790  if (!empty($result['flexParentDatabaseRow']['pid'])) {
791  $effectivePid = $result['flexParentDatabaseRow']['pid'];
792  } elseif (!$effectivePid && !empty($result['databaseRow']['pid'])) {
793  // Use pid from database row if in inline context
794  $effectivePid = $result['databaseRow']['pid'];
795  }
796  }
797 
798  $siteRootUid = 0;
799  foreach ($result['rootline'] as $rootlinePage) {
800  if (!empty($rootlinePage['is_siteroot'])) {
801  $siteRootUid = (int)$rootlinePage['uid'];
802  break;
803  }
804  }
805 
806  $pageTsConfigId = 0;
807  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'])
808  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID']
809  ) {
810  $pageTsConfigId = (int)$result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_ID'];
811  }
812 
813  $pageTsConfigIdList = 0;
814  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'])
815  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST']
816  ) {
817  $pageTsConfigIdList = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_IDLIST'];
818  }
819  $pageTsConfigIdListArray = ‪GeneralUtility::trimExplode(',', $pageTsConfigIdList, true);
820  $pageTsConfigIdList = [];
821  foreach ($pageTsConfigIdListArray as $pageTsConfigIdListElement) {
822  if (‪MathUtility::canBeInterpretedAsInteger($pageTsConfigIdListElement)) {
823  $pageTsConfigIdList[] = (int)$pageTsConfigIdListElement;
824  }
825  }
826  $pageTsConfigIdList = implode(',', $pageTsConfigIdList);
827 
828  $pageTsConfigString = '';
829  if (isset($result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'])
830  && $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR']
831  ) {
832  $pageTsConfigString = $result['pageTsConfig']['TCEFORM.'][$localTable . '.'][$localFieldName . '.']['PAGE_TSCONFIG_STR'];
833  $pageTsConfigString = $connection->quote($pageTsConfigString);
834  }
835 
836  $foreignTableClause = str_replace(
837  [
838  '###CURRENT_PID###',
839  '###THIS_UID###',
840  '###SITEROOT###',
841  '###PAGE_TSCONFIG_ID###',
842  '###PAGE_TSCONFIG_IDLIST###',
843  '\'###PAGE_TSCONFIG_STR###\'',
844  '###PAGE_TSCONFIG_STR###',
845  ],
846  [
847  (int)$effectivePid,
848  (int)$result['databaseRow']['uid'],
849  $siteRootUid,
850  $pageTsConfigId,
851  $pageTsConfigIdList,
852  $pageTsConfigString,
853  $pageTsConfigString,
854  ],
855  $foreignTableClause
856  );
857 
858  $parsedSiteConfiguration = $this->parseSiteConfiguration($result['site'], $foreignTableClause);
859  if ($parsedSiteConfiguration !== []) {
860  $parsedSiteConfiguration = $this->quoteParsedSiteConfiguration($connection, $parsedSiteConfiguration);
861  $foreignTableClause = $this->replaceParsedSiteConfiguration($foreignTableClause, $parsedSiteConfiguration);
862  }
863  }
864 
865  // Split the clause into an array with keys WHERE, GROUPBY, ORDERBY, LIMIT
866  // Prepend a space to make sure "[[:space:]]+" will find a space there for the first element.
867  $foreignTableClause = ' ' . $foreignTableClause;
868  $foreignTableClauseArray = [
869  'WHERE' => '',
870  'GROUPBY' => '',
871  'ORDERBY' => '',
872  'LIMIT' => '',
873  ];
874  // Find LIMIT
875  $reg = [];
876  if (preg_match('/^(.*)[[:space:]]+LIMIT[[:space:]]+([[:alnum:][:space:],._]+)$/is', $foreignTableClause, $reg)) {
877  $foreignTableClauseArray['LIMIT'] = ‪GeneralUtility::intExplode(',', trim($reg[2]), true);
878  $foreignTableClause = $reg[1];
879  }
880  // Find ORDER BY
881  $reg = [];
882  if (preg_match('/^(.*)[[:space:]]+ORDER[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
883  $foreignTableClauseArray['ORDERBY'] = ‪QueryHelper::parseOrderBy(trim($reg[2]));
884  $foreignTableClause = $reg[1];
885  }
886  // Find GROUP BY
887  $reg = [];
888  if (preg_match('/^(.*)[[:space:]]+GROUP[[:space:]]+BY[[:space:]]+([[:alnum:][:space:],._()"]+)$/is', $foreignTableClause, $reg)) {
889  $foreignTableClauseArray['GROUPBY'] = ‪QueryHelper::parseGroupBy(trim($reg[2]));
890  $foreignTableClause = $reg[1];
891  }
892  // Rest is assumed to be "WHERE" clause
893  $foreignTableClauseArray['WHERE'] = ‪QueryHelper::stripLogicalOperatorPrefix($foreignTableClause);
894 
895  return $foreignTableClauseArray;
896  }
897 
905  protected function ‪parseSiteConfiguration(?‪SiteInterface $site, string $input): array
906  {
907  // Since we need to access the configuration, early return in case
908  // we don't deal with an instance of Site (e.g. null or NullSite).
909  if (!$site instanceof ‪Site) {
910  return [];
911  }
912 
913  $siteClausesRegEx = '/###SITE:([^#]+)###/m';
914  preg_match_all($siteClausesRegEx, $input, $matches, PREG_SET_ORDER);
915 
916  if (empty($matches)) {
917  return [];
918  }
919 
920  $replacements = [];
921  $configuration = $site->getConfiguration();
922  array_walk($matches, static function ($match) use (&$replacements, &$configuration) {
923  $key = $match[1];
924  try {
925  $value = ‪ArrayUtility::getValueByPath($configuration, $key, '.');
926  } catch (‪MissingArrayPathException $exception) {
927  $value = '';
928  }
929 
930  $replacements[$match[0]] = $value;
931  });
932 
933  return $replacements;
934  }
935 
936  protected function ‪quoteParsedSiteConfiguration(‪Connection $connection, array $parsedSiteConfiguration): array
937  {
938  foreach ($parsedSiteConfiguration as $key => $value) {
939  if (is_int($value)) {
940  // int values are safe, nothing to do here
941  continue;
942  }
943  if (is_string($value)) {
944  $parsedSiteConfiguration[$key] = $connection->quote($value);
945  continue;
946  }
947  if (is_array($value)) {
948  $parsedSiteConfiguration[$key] = implode(',', $this->quoteParsedSiteConfiguration($connection, $value));
949  continue;
950  }
951  if (is_bool($value)) {
952  $parsedSiteConfiguration[$key] = (int)$value;
953  continue;
954  }
955  throw new \InvalidArgumentException(
956  sprintf('Cannot quote site configuration setting "%s" of type "%s", only "int", "bool", "string" and "array" are supported', $key, gettype($value)),
957  1630324435
958  );
959  }
960 
961  return $parsedSiteConfiguration;
962  }
963 
964  protected function ‪replaceParsedSiteConfiguration(string $input, array $parsedSiteConfiguration): string
965  {
966  return str_replace(
967  array_keys($parsedSiteConfiguration),
968  array_values($parsedSiteConfiguration),
969  $input
970  );
971  }
972 
976  protected function ‪parseStartingPointsFromSiteConfiguration(array $result, array $fieldConfig): array
977  {
978  if (!isset($fieldConfig['config']['treeConfig']['startingPoints'])) {
979  return $fieldConfig;
980  }
981 
982  $parsedSiteConfiguration = $this->parseSiteConfiguration($result['site'], $fieldConfig['config']['treeConfig']['startingPoints']);
983  if ($parsedSiteConfiguration !== []) {
984  // $this->quoteParsedSiteConfiguration() is omitted on purpose, all values are cast to integers
985  $parsedSiteConfiguration = array_unique(array_map(static function ($value): string {
986  if (is_array($value)) {
987  return implode(',', array_map('intval', $value));
988  }
989 
990  return implode(',', ‪GeneralUtility::intExplode(',', $value, true));
991  }, $parsedSiteConfiguration));
992  $resolvedStartingPoints = $this->replaceParsedSiteConfiguration($fieldConfig['config']['treeConfig']['startingPoints'], $parsedSiteConfiguration);
993  // Add the resolved starting points while removing empty values
994  $fieldConfig['config']['treeConfig']['startingPoints'] = implode(
995  ',',
996  ‪GeneralUtility::trimExplode(',', $resolvedStartingPoints, true)
997  );
998  }
999 
1000  return $fieldConfig;
1001  }
1002 
1010  protected function ‪processDatabaseFieldValue(array $row, $fieldName)
1011  {
1012  $currentDatabaseValues = array_key_exists($fieldName, $row)
1013  ? $row[$fieldName]
1014  : '';
1015  if (!is_array($currentDatabaseValues)) {
1016  $currentDatabaseValues = ‪GeneralUtility::trimExplode(',', $currentDatabaseValues, true);
1017  }
1018  return $currentDatabaseValues;
1019  }
1020 
1032  protected function ‪processSelectFieldValue(array $result, $fieldName, array $staticValues)
1033  {
1034  $fieldConfig = $result['processedTca']['columns'][$fieldName];
1035 
1036  $currentDatabaseValueArray = array_key_exists($fieldName, $result['databaseRow']) ? $result['databaseRow'][$fieldName] : [];
1037  $newDatabaseValueArray = [];
1038 
1039  // Add all values that were defined by static methods and do not come from the relation
1040  // e.g. TCA, TSconfig, itemProcFunc etc.
1041  foreach ($currentDatabaseValueArray as $value) {
1042  if (isset($staticValues[$value])) {
1043  $newDatabaseValueArray[] = $value;
1044  }
1045  }
1046 
1047  if (isset($fieldConfig['config']['foreign_table']) && !empty($fieldConfig['config']['foreign_table'])) {
1048  $relationHandler = GeneralUtility::makeInstance(RelationHandler::class);
1049  $relationHandler->registerNonTableValues = !empty($fieldConfig['config']['allowNonIdValues']);
1050  if (!empty($fieldConfig['config']['MM']) && $result['command'] !== 'new') {
1051  // MM relation
1052  $relationHandler->start(
1053  implode(',', $currentDatabaseValueArray),
1054  $fieldConfig['config']['foreign_table'],
1055  $fieldConfig['config']['MM'],
1056  $result['databaseRow']['uid'],
1057  $result['tableName'],
1058  $fieldConfig['config']
1059  );
1060  $relationHandler->processDeletePlaceholder();
1061  $newDatabaseValueArray = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
1062  } else {
1063  // Non MM relation
1064  // If not dealing with MM relations, use default live uid, not versioned uid for record relations
1065  $relationHandler->start(
1066  implode(',', $currentDatabaseValueArray),
1067  $fieldConfig['config']['foreign_table'],
1068  '',
1069  $this->getLiveUid($result),
1070  $result['tableName'],
1071  $fieldConfig['config']
1072  );
1073  $relationHandler->processDeletePlaceholder();
1074  $databaseIds = array_merge($newDatabaseValueArray, $relationHandler->getValueArray());
1075  // remove all items from the current DB values if not available as relation or static value anymore
1076  $newDatabaseValueArray = array_values(array_intersect($currentDatabaseValueArray, $databaseIds));
1077  }
1078  }
1079 
1080  if ($fieldConfig['config']['multiple'] ?? false) {
1081  return $newDatabaseValueArray;
1082  }
1083  return array_unique($newDatabaseValueArray);
1084  }
1085 
1097  public function ‪translateLabels(array $result, array $itemArray, $table, $fieldName)
1098  {
1099  $languageService = $this->getLanguageService();
1100 
1101  foreach ($itemArray as $key => $item) {
1102  $labelIndex = $item[1] ?? '';
1103 
1104  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex])
1105  && !empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex])
1106  ) {
1107  $label = $languageService->sL($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altLabels.'][$labelIndex]);
1108  } else {
1109  $label = $languageService->sL(trim($item[0] ?? ''));
1110  }
1111  $value = strlen((string)($item[1] ?? '')) > 0 ? $item[1] : '';
1112  $icon = !empty($item[2]) ? $item[2] : null;
1113  $groupId = $item[3] ?? null;
1114  $helpText = null;
1115  if (!empty($item[4])) {
1116  if (\is_string($item[4])) {
1117  $helpText = $languageService->sL($item[4]);
1118  } else {
1119  $helpText = $item[4];
1120  }
1121  }
1122  $itemArray[$key] = [
1123  $label,
1124  $value,
1125  $icon,
1126  $groupId,
1127  $helpText,
1128  ];
1129  }
1130 
1131  return $itemArray;
1132  }
1133 
1144  public function ‪addIconFromAltIcons(array $result, array $items, string $table, string $fieldName): array
1145  {
1146  foreach ($items as &$item) {
1147  if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item[1]])
1148  && !empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item[1]])
1149  ) {
1150  $item[2] = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['altIcons.'][$item[1]];
1151  }
1152  }
1153 
1154  return $items;
1155  }
1156 
1168  public function ‪sanitizeItemArray($itemArray, $tableName, $fieldName)
1169  {
1170  if (!is_array($itemArray)) {
1171  $itemArray = [];
1172  }
1173  foreach ($itemArray as $item) {
1174  if (!is_array($item)) {
1175  throw new \UnexpectedValueException(
1176  'An item in field ' . $fieldName . ' of table ' . $tableName . ' is not an array as expected',
1177  1439288036
1178  );
1179  }
1180  }
1181 
1182  return $itemArray;
1183  }
1184 
1193  protected function ‪getLiveUid(array $result)
1194  {
1195  $table = $result['tableName'];
1196  $row = $result['databaseRow'];
1197  $uid = $row['uid'] ?? 0;
1198  if (BackendUtility::isTableWorkspaceEnabled($table) && (int)($row['t3ver_oid'] ?? 0) > 0) {
1199  $uid = $row['t3ver_oid'];
1200  }
1201  return $uid;
1202  }
1203 
1207  protected function ‪getLanguageService()
1208  {
1209  return ‪$GLOBALS['LANG'];
1210  }
1211 
1215  protected function ‪getBackendUser()
1216  {
1217  return ‪$GLOBALS['BE_USER'];
1218  }
1219 }
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\sanitizeItemArray
‪array sanitizeItemArray($itemArray, $tableName, $fieldName)
Definition: AbstractItemProvider.php:1168
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseOrderBy
‪static array array[] parseOrderBy(string $input)
Definition: QueryHelper.php:44
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:999
‪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:138
‪TYPO3\CMS\Core\Utility\ArrayUtility\keepItemsInArray
‪static array keepItemsInArray(array $array, $keepItems, $getValueFunc=null)
Definition: ArrayUtility.php:718
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\replaceParsedSiteConfiguration
‪replaceParsedSiteConfiguration(string $input, array $parsedSiteConfiguration)
Definition: AbstractItemProvider.php:964
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getBackendUser
‪BackendUserAuthentication getBackendUser()
Definition: AbstractItemProvider.php:1215
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:49
‪TYPO3\CMS\Core\Utility\MathUtility\canBeInterpretedAsInteger
‪static bool canBeInterpretedAsInteger($var)
Definition: MathUtility.php:74
‪TYPO3\CMS\Core\Resource\ResourceStorage\getUid
‪int getUid()
Definition: ResourceStorage.php:330
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserLanguageFieldRestriction
‪array removeItemsByUserLanguageFieldRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:503
‪TYPO3\CMS\Core\Database\RelationHandler
Definition: RelationHandler.php:37
‪TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException
Definition: MissingArrayPathException.php:27
‪TYPO3
‪TYPO3\CMS\Core\Database\Query\QueryHelper\parseGroupBy
‪static array string[] parseGroupBy(string $input)
Definition: QueryHelper.php:102
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLanguageService
‪LanguageService getLanguageService()
Definition: AbstractItemProvider.php:1207
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addIconFromAltIcons
‪array addIconFromAltIcons(array $result, array $items, string $table, string $fieldName)
Definition: AbstractItemProvider.php:1144
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\translateLabels
‪array translateLabels(array $result, array $itemArray, $table, $fieldName)
Definition: AbstractItemProvider.php:1097
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\addItemsFromSpecial
‪array addItemsFromSpecial(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:176
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Core\Versioning\VersionState\DELETE_PLACEHOLDER
‪const DELETE_PLACEHOLDER
Definition: VersionState.php:61
‪TYPO3\CMS\Core\Database\Query\QueryHelper\quoteDatabaseIdentifiers
‪static string quoteDatabaseIdentifiers(Connection $connection, string $sql)
Definition: QueryHelper.php:228
‪TYPO3\CMS\Core\Versioning\VersionState\MOVE_POINTER
‪const MOVE_POINTER
Definition: VersionState.php:78
‪TYPO3\CMS\Core\Type\Bitmask\Permission
Definition: Permission.php:26
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\parseStartingPointsFromSiteConfiguration
‪parseStartingPointsFromSiteConfiguration(array $result, array $fieldConfig)
Definition: AbstractItemProvider.php:976
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processForeignTableClause
‪array processForeignTableClause(array $result, $foreignTableName, $localFieldName)
Definition: AbstractItemProvider.php:746
‪TYPO3\CMS\Core\Type\Enumeration\cast
‪static static cast($value)
Definition: Enumeration.php:186
‪TYPO3\CMS\Core\Utility\ArrayUtility\getValueByPath
‪static mixed getValueByPath(array $array, $path, $delimiter='/')
Definition: ArrayUtility.php:180
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\getLiveUid
‪int string getLiveUid(array $result)
Definition: AbstractItemProvider.php:1193
‪TYPO3\CMS\Core\Database\Query\QueryHelper
Definition: QueryHelper.php:32
‪TYPO3\CMS\Core\Resource\FileRepository
Definition: FileRepository.php:33
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserStorageRestriction
‪array removeItemsByUserStorageRestriction(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:593
‪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:563
‪TYPO3\CMS\Core\Configuration\Features
Definition: Features.php:56
‪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:905
‪TYPO3\CMS\Backend\Form\FormDataProvider
Definition: AbstractDatabaseRecordProvider.php:16
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByKeepItemsPageTsConfig
‪array removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:436
‪TYPO3\CMS\Core\Versioning\VersionState
Definition: VersionState.php:24
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processDatabaseFieldValue
‪array processDatabaseFieldValue(array $row, $fieldName)
Definition: AbstractItemProvider.php:1010
‪TYPO3\CMS\Core\Resource\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:38
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\quoteParsedSiteConfiguration
‪quoteParsedSiteConfiguration(Connection $connection, array $parsedSiteConfiguration)
Definition: AbstractItemProvider.php:936
‪TYPO3\CMS\Core\Resource\ResourceStorage
Definition: ResourceStorage.php:125
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:26
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\processSelectFieldValue
‪array processSelectFieldValue(array $result, $fieldName, array $staticValues)
Definition: AbstractItemProvider.php:1032
‪TYPO3\CMS\Core\Database\Query\QueryHelper\stripLogicalOperatorPrefix
‪static string stripLogicalOperatorPrefix(string $constraint)
Definition: QueryHelper.php:171
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:24
‪TYPO3\CMS\Core\Hooks\TcaItemsProcessorFunctions
Definition: TcaItemsProcessorFunctions.php:35
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction
Definition: DeletedRestriction.php:28
‪if
‪if(PHP_SAPI !=='cli')
Definition: checkNamespaceIntegrity.php:25
‪TYPO3\CMS\Core\Utility\GeneralUtility\intExplode
‪static int[] intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
Definition: GeneralUtility.php:927
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:22
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByUserAuthMode
‪array removeItemsByUserAuthMode(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:532
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider
Definition: AbstractItemProvider.php:50
‪TYPO3\CMS\Core\Messaging\AbstractMessage\ERROR
‪const ERROR
Definition: AbstractMessage.php:31
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\removeItemsByRemoveItemsPageTsConfig
‪array removeItemsByRemoveItemsPageTsConfig(array $result, $fieldName, array $items)
Definition: AbstractItemProvider.php:469
‪TYPO3\CMS\Backend\Form\FormDataProvider\AbstractItemProvider\buildForeignTableQueryBuilder
‪buildForeignTableQueryBuilder(array $result, string $localFieldName, bool $selectAllFields=false)
Definition: AbstractItemProvider.php:626
‪TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction
Definition: WorkspaceRestriction.php:40