From 4d254ef9798b5439503100146df7f3867524ec30 Mon Sep 17 00:00:00 2001 From: Sebastian Michaelsen Date: Fri, 1 Aug 2025 16:21:04 +0200 Subject: [PATCH] feat: add InlineItemsHelper --- .../Helpers/InlineItemsHelper.php | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Classes/DataProviding/Helpers/InlineItemsHelper.php diff --git a/Classes/DataProviding/Helpers/InlineItemsHelper.php b/Classes/DataProviding/Helpers/InlineItemsHelper.php new file mode 100644 index 0000000..c5b522f --- /dev/null +++ b/Classes/DataProviding/Helpers/InlineItemsHelper.php @@ -0,0 +1,108 @@ + $parentRecord + * @return list> + */ + public function loadInlineItems(array $parentRecord, string $inlineFieldName, string $parentTable = 'tt_content'): array + { + // if the field is empty, and we're not in a workspace context, then there are no inline items + /** @var int|string $versioningWorkspaceId */ + $versioningWorkspaceId = $this->context->getPropertyFromAspect('workspace', 'id'); + $versioningWorkspaceId = (int)$versioningWorkspaceId; + if (empty($parentRecord[$inlineFieldName]) && $versioningWorkspaceId === 0) { + return []; + } + + $inlineFieldTca = $this->getInlineFieldTca($inlineFieldName, $parentTable); + $foreignTable = $inlineFieldTca['config']['foreign_table'] ?? null; + if ($foreignTable === null) { + throw new \Exception( + sprintf('Could not load inline items for field "%s". Missing \'foreign_table\' in its TCA configuration', $inlineFieldName), + 1686299043 + ); + } + $foreignField = $inlineFieldTca['config']['foreign_field'] ?? null; + $foreignTableTca = $GLOBALS['TCA'][$foreignTable]; + $foreignSortby = $inlineFieldTca['config']['foreign_sortby'] ?? $foreignTableTca['ctrl']['sortby'] ?? null; + $queryBuilder = $this->connectionPool->getQueryBuilderForTable($foreignTable); + $queryBuilder->getRestrictions()->removeAll(); + + $parentRecordId = $parentRecord['_LOCALIZED_UID'] ?? $parentRecord['uid'] ?? 0; + $constraints = []; + if (!empty($foreignField)) { + $constraints[] = $queryBuilder->expr()->eq($foreignField, $queryBuilder->createNamedParameter($parentRecordId, Connection::PARAM_INT)); + } else { + $itemsUidList = GeneralUtility::intExplode(',', (string)($parentRecord[$inlineFieldName] ?? ''), true); + if (empty($itemsUidList)) { + return []; + } + $constraints[] = $queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($itemsUidList, ArrayParameterType::INTEGER)); + } + if (isset($foreignTableTca['ctrl']['languageField'])) { + $constraints[] = $queryBuilder->expr()->in($foreignTableTca['ctrl']['languageField'], $queryBuilder->createNamedParameter([-1, $parentRecord['sys_language_uid'] ?? 0], ArrayParameterType::INTEGER)); + } + $constraints[] = QueryHelper::stripLogicalOperatorPrefix($this->pageRepository->enableFields($foreignTable)); + $queryBuilder->select('*')->from($foreignTable)->where(...$constraints); + if ($foreignSortby) { + $queryBuilder->orderBy($foreignSortby); + } + $queriedItems = $queryBuilder->executeQuery()->fetchAllAssociative(); + $processedItems = []; + foreach ($queriedItems as $item) { + // workspace overlay: + $this->pageRepository->versionOL($foreignTable, $item); + if ($item === false) { + continue; + } + $processedItems[] = $item; + } + + if (empty($foreignField)) { + // sort items by uid list + $itemsUidList = GeneralUtility::intExplode(',', (string)$parentRecord[$inlineFieldName], true); + // sort $processedItems by the position of their uid in $itemsUidList + usort($processedItems, static fn(array $itemA, array $itemB) => array_search($itemA['uid'], $itemsUidList) <=> array_search($itemB['uid'], $itemsUidList)); + } elseif (!empty($foreignSortby)) { + // sort items again after workspace overlay + usort($processedItems, static fn(array $itemA, array $itemB) => $itemA[$foreignSortby] <=> $itemB[$foreignSortby]); + } + + return $processedItems; + } + + /** + * @return array{config: array{foreign_table?: string, foreign_field?: string, foreign_sortby?: string}, label: string, type: string} + */ + protected function getInlineFieldTca(string $inlineFieldName, string $localTableName = 'tt_content'): array + { + if (!isset($GLOBALS['TCA'][$localTableName]['columns'][$inlineFieldName])) { + throw new \Exception('Tried to process inline records for non existing field ' . $localTableName . '.' . $inlineFieldName, 1587038305); + } + return $GLOBALS['TCA'][$localTableName]['columns'][$inlineFieldName]; + } +}