1) { throw new \InvalidArgumentException( '$routeValuePrefix must be string with one character', 1537277136 ); } $this->settings = $settings; $this->tableName = $tableName; $this->routeFieldName = $routeFieldName; $this->routeValuePrefix = $routeValuePrefix; $schema = GeneralUtility::makeInstance(TcaSchemaFactory::class)->get($this->tableName); if ($schema->isLanguageAware()) { $this->languageFieldName = $schema->getCapability(TcaSchemaCapability::Language)->getLanguageField()->getName(); $this->languageParentFieldName = $schema->getCapability(TcaSchemaCapability::Language)->getTranslationOriginPointerField()->getName(); } else { $this->languageFieldName = null; $this->languageParentFieldName = null; } $this->persistenceFieldNames = $this->buildPersistenceFieldNames(); $this->slugUniqueInSite = $this->isSlugUniqueInSite($this->tableName, $this->routeFieldName); } /** * {@inheritdoc} */ public function generate(string $value): ?string { $result = $this->findByIdentifier($value); $result = $this->resolveOverlay($result); if (!isset($result[$this->routeFieldName])) { return null; } return $this->purgeRouteValuePrefix( (string)$result[$this->routeFieldName] ); } /** * {@inheritdoc} */ public function resolve(string $value): ?string { $value = $this->routeValuePrefix . $this->purgeRouteValuePrefix($value); $result = $this->findByRouteFieldValue($value); $translatedValue = $this->languageParentFieldName ? ($result[$this->languageParentFieldName] ?? null) : null; if ($translatedValue) { return (string)$translatedValue; } if (isset($result['uid'])) { return (string)$result['uid']; } return null; } /** * @return string[] */ protected function buildPersistenceFieldNames(): array { return array_filter([ 'uid', 'pid', $this->routeFieldName, $this->languageFieldName, $this->languageParentFieldName, ]); } /** * @return string */ protected function purgeRouteValuePrefix(?string $value): ?string { if (empty($this->routeValuePrefix) || $value === null) { return $value; } return ltrim($value, $this->routeValuePrefix); } protected function findByIdentifier(string $value): ?array { if (!MathUtility::canBeInterpretedAsInteger($value)) { return null; } $queryBuilder = $this->createQueryBuilder(); $result = $queryBuilder ->select(...$this->persistenceFieldNames) ->where($queryBuilder->expr()->eq( 'uid', $queryBuilder->createNamedParameter($value, Connection::PARAM_INT) )) ->executeQuery() ->fetchAssociative(); return $result !== false ? $result : null; } protected function findByRouteFieldValue(string $value): ?array { $languageAware = $this->languageFieldName !== null && $this->languageParentFieldName !== null; $queryBuilder = $this->createQueryBuilder(); $constraints = [ $queryBuilder->expr()->eq( $this->routeFieldName, $queryBuilder->createNamedParameter($value) ), ]; $languageIds = null; if ($languageAware) { $languageIds = $this->resolveAllRelevantLanguageIds(); $constraints[] = $queryBuilder->expr()->in( $this->languageFieldName, $queryBuilder->createNamedParameter($languageIds, Connection::PARAM_INT_ARRAY) ); } $results = $queryBuilder ->select(...$this->persistenceFieldNames) ->where(...$constraints) ->executeQuery() ->fetchAllAssociative(); // limit results to be contained in rootPageId of current Site // (which is defining the route configuration currently being processed) if ($this->slugUniqueInSite) { $results = array_values($this->filterContainedInSite($results)); } // return first result record in case table is not language aware if (!$languageAware) { return $results[0] ?? null; } // post-process language fallbacks return $this->resolveLanguageFallback($results, $this->languageFieldName, $languageIds); } protected function createQueryBuilder(): QueryBuilder { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable($this->tableName) ->from($this->tableName); $queryBuilder->setRestrictions( GeneralUtility::makeInstance(FrontendRestrictionContainer::class, GeneralUtility::makeInstance(Context::class)) ); // Frontend Groups are not available at this time // So this must be excluded to allow access restricted records $queryBuilder->getRestrictions()->removeByType(FrontendGroupRestriction::class); return $queryBuilder; } protected function resolveOverlay(?array $record): ?array { $languageId = $this->siteLanguage->getLanguageId(); if ($record === null || $languageId === 0) { return $record; } $pageRepository = $this->createPageRepository(); return $pageRepository->getLanguageOverlay($this->tableName, $record) ?: null; } protected function createPageRepository(): PageRepository { $context = clone GeneralUtility::makeInstance(Context::class); $context->setAspect( 'language', LanguageAspectFactory::createFromSiteLanguage($this->siteLanguage) ); return GeneralUtility::makeInstance( PageRepository::class, $context ); } }