diff --git a/typo3/sysext/core/Classes/Routing/Aspect/DelegateInterface.php b/typo3/sysext/core/Classes/Routing/Aspect/DelegateInterface.php index 8145e7fd25f5decc95f0144398ca2fc1c004d151..27eb7feac533e83f1e4dc507cd535ddf98258b4f 100644 --- a/typo3/sysext/core/Classes/Routing/Aspect/DelegateInterface.php +++ b/typo3/sysext/core/Classes/Routing/Aspect/DelegateInterface.php @@ -19,6 +19,8 @@ namespace TYPO3\CMS\Core\Routing\Aspect; /** * Interface that describes delegations of tasks to different processors * when resolving or generating parameters for URLs. + * + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 */ interface DelegateInterface { diff --git a/typo3/sysext/core/Classes/Routing/Aspect/PersistedAliasMapper.php b/typo3/sysext/core/Classes/Routing/Aspect/PersistedAliasMapper.php index ebfc87066282b1e44e9795f67560bf49504ef916..9b049bfa86701bf83c33742ecf641d1ac23d4cbc 100644 --- a/typo3/sysext/core/Classes/Routing/Aspect/PersistedAliasMapper.php +++ b/typo3/sysext/core/Classes/Routing/Aspect/PersistedAliasMapper.php @@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Context\LanguageAspectFactory; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Domain\Repository\PageRepository; +use TYPO3\CMS\Core\Routing\Legacy\PersistedAliasMapperLegacyTrait; use TYPO3\CMS\Core\Site\SiteLanguageAwareInterface; use TYPO3\CMS\Core\Site\SiteLanguageAwareTrait; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -47,6 +48,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMappableAspectInterface, SiteLanguageAwareInterface { use SiteLanguageAwareTrait; + use PersistedAliasMapperLegacyTrait; /** * @var array @@ -69,14 +71,14 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa protected $routeValuePrefix; /** - * @var PersistenceDelegate + * @var string[] */ - protected $persistenceDelegate; + protected $persistenceFieldNames; /** - * @var string[] + * @var string|null */ - protected $persistenceFieldNames; + protected $languageFieldName; /** * @var string|null @@ -116,8 +118,9 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa $this->tableName = $tableName; $this->routeFieldName = $routeFieldName; $this->routeValuePrefix = $routeValuePrefix; - $this->persistenceFieldNames = $this->buildPersistenceFieldNames(); + $this->languageFieldName = $GLOBALS['TCA'][$this->tableName]['ctrl']['languageField'] ?? null; $this->languageParentFieldName = $GLOBALS['TCA'][$this->tableName]['ctrl']['transOrigPointerField'] ?? null; + $this->persistenceFieldNames = $this->buildPersistenceFieldNames(); } /** @@ -125,9 +128,7 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa */ public function generate(string $value): ?string { - $result = $this->getPersistenceDelegate()->generate([ - 'uid' => $value - ]); + $result = $this->findByIdentifier($value); $result = $this->resolveOverlay($result); if (!isset($result[$this->routeFieldName])) { return null; @@ -143,9 +144,7 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa public function resolve(string $value): ?string { $value = $this->routeValuePrefix . $this->purgeRouteValuePrefix($value); - $result = $this->getPersistenceDelegate()->resolve([ - $this->routeFieldName => $value - ]); + $result = $this->findByRouteFieldValue($value); if ($result[$this->languageParentFieldName] ?? null > 0) { return (string)$result[$this->languageParentFieldName]; } @@ -164,8 +163,8 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa 'uid', 'pid', $this->routeFieldName, - $GLOBALS['TCA'][$this->tableName]['ctrl']['languageField'] ?? null, - $GLOBALS['TCA'][$this->tableName]['ctrl']['transOrigPointerField'] ?? null, + $this->languageFieldName, + $this->languageParentFieldName, ]); } @@ -181,55 +180,39 @@ class PersistedAliasMapper implements PersistedMappableAspectInterface, StaticMa return ltrim($value, $this->routeValuePrefix); } - /** - * @return PersistenceDelegate - */ - protected function getPersistenceDelegate(): PersistenceDelegate + protected function findByIdentifier(string $value): ?array { - if ($this->persistenceDelegate !== null) { - return $this->persistenceDelegate; - } - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable($this->tableName) - ->from($this->tableName); - // @todo Restrictions (Hidden? Workspace?) - - $resolveModifier = function (QueryBuilder $queryBuilder, array $values) { - return $queryBuilder->select(...$this->persistenceFieldNames)->where( - ...$this->createFieldConstraints($queryBuilder, $values) - ); - }; - $generateModifier = function (QueryBuilder $queryBuilder, array $values) { - return $queryBuilder->select(...$this->persistenceFieldNames)->where( - ...$this->createFieldConstraints($queryBuilder, $values) - ); - }; + $queryBuilder = $this->createQueryBuilder(); + $result = $queryBuilder + ->select(...$this->persistenceFieldNames) + ->where($queryBuilder->expr()->eq( + 'uid', + $queryBuilder->createNamedParameter($value, \PDO::PARAM_INT) + )) + ->execute() + ->fetch(); + return $result !== false ? $result : null; + } - return $this->persistenceDelegate = new PersistenceDelegate( - $queryBuilder, - $resolveModifier, - $generateModifier - ); + protected function findByRouteFieldValue(string $value): ?array + { + $queryBuilder = $this->createQueryBuilder(); + $result = $queryBuilder + ->select(...$this->persistenceFieldNames) + ->where($queryBuilder->expr()->eq( + $this->routeFieldName, + $queryBuilder->createNamedParameter($value, \PDO::PARAM_STR) + )) + ->execute() + ->fetch(); + return $result !== false ? $result : null; } - /** - * @param QueryBuilder $queryBuilder - * @param array $values - * @return array - */ - protected function createFieldConstraints(QueryBuilder $queryBuilder, array $values): array + protected function createQueryBuilder(): QueryBuilder { - $constraints = []; - foreach ($values as $fieldName => $fieldValue) { - $constraints[] = $queryBuilder->expr()->eq( - $fieldName, - $queryBuilder->createNamedParameter( - $fieldValue, - \PDO::PARAM_STR - ) - ); - } - return $constraints; + return GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($this->tableName) + ->from($this->tableName); } /** diff --git a/typo3/sysext/core/Classes/Routing/Aspect/PersistedPatternMapper.php b/typo3/sysext/core/Classes/Routing/Aspect/PersistedPatternMapper.php index c1a0a4c1ed657973d74972b7f748f1e8419a03e1..f0c5b22a811baee76d1bdab76380969928965d9c 100644 --- a/typo3/sysext/core/Classes/Routing/Aspect/PersistedPatternMapper.php +++ b/typo3/sysext/core/Classes/Routing/Aspect/PersistedPatternMapper.php @@ -21,6 +21,7 @@ use TYPO3\CMS\Core\Context\LanguageAspectFactory; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Domain\Repository\PageRepository; +use TYPO3\CMS\Core\Routing\Legacy\PersistedPatternMapperLegacyTrait; use TYPO3\CMS\Core\Site\SiteLanguageAwareInterface; use TYPO3\CMS\Core\Site\SiteLanguageAwareTrait; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -50,6 +51,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; class PersistedPatternMapper implements PersistedMappableAspectInterface, StaticMappableAspectInterface, SiteLanguageAwareInterface { use SiteLanguageAwareTrait; + use PersistedPatternMapperLegacyTrait; protected const PATTERN_RESULT = '#\{(?P<fieldName>[^}]+)\}#'; @@ -78,11 +80,6 @@ class PersistedPatternMapper implements PersistedMappableAspectInterface, Static */ protected $routeFieldResultNames; - /** - * @var PersistenceDelegate - */ - protected $persistenceDelegate; - /** * @var string|null */ @@ -127,9 +124,7 @@ class PersistedPatternMapper implements PersistedMappableAspectInterface, Static */ public function generate(string $value): ?string { - $result = $this->getPersistenceDelegate()->generate([ - 'uid' => $value - ]); + $result = $this->findByIdentifier($value); $result = $this->resolveOverlay($result); return $this->createRouteResult($result); } @@ -143,7 +138,7 @@ class PersistedPatternMapper implements PersistedMappableAspectInterface, Static return null; } $values = $this->filterNamesKeys($matches); - $result = $this->getPersistenceDelegate()->resolve($values); + $result = $this->findByRouteFieldValues($values); if ($result[$this->languageParentFieldName] ?? null > 0) { return (string)$result[$this->languageParentFieldName]; } @@ -193,51 +188,46 @@ class PersistedPatternMapper implements PersistedMappableAspectInterface, Static ); } - /** - * @return PersistenceDelegate - */ - protected function getPersistenceDelegate(): PersistenceDelegate + protected function findByIdentifier(string $value): ?array { - if ($this->persistenceDelegate !== null) { - return $this->persistenceDelegate; - } - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable($this->tableName) - ->from($this->tableName); - // @todo Restrictions (Hidden? Workspace?) + $queryBuilder = $this->createQueryBuilder(); + $result = $queryBuilder + ->select('*') + ->where($queryBuilder->expr()->eq( + 'uid', + $queryBuilder->createNamedParameter($value, \PDO::PARAM_INT) + )) + ->execute() + ->fetch(); + return $result !== false ? $result : null; + } - $resolveModifier = function (QueryBuilder $queryBuilder, array $values) { - return $queryBuilder->select('*')->where( - ...$this->createFieldConstraints($queryBuilder, $values, true) - ); - }; - $generateModifier = function (QueryBuilder $queryBuilder, array $values) { - return $queryBuilder->select('*')->where( - ...$this->createFieldConstraints($queryBuilder, $values) - ); - }; + protected function findByRouteFieldValues(array $values): ?array + { + $queryBuilder = $this->createQueryBuilder(); + $result = $queryBuilder + ->select('*') + ->where(...$this->createRouteFieldConstraints($queryBuilder, $values)) + ->execute() + ->fetch(); + return $result !== false ? $result : null; + } - return $this->persistenceDelegate = new PersistenceDelegate( - $queryBuilder, - $resolveModifier, - $generateModifier - ); + protected function createQueryBuilder(): QueryBuilder + { + return GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($this->tableName) + ->from($this->tableName); } /** * @param QueryBuilder $queryBuilder * @param array $values - * @param bool $resolveExpansion * @return array */ - protected function createFieldConstraints( - QueryBuilder $queryBuilder, - array $values, - bool $resolveExpansion = false - ): array { - $languageExpansion = $this->languageParentFieldName - && $resolveExpansion - && isset($values['uid']); + protected function createRouteFieldConstraints(QueryBuilder $queryBuilder, array $values): array + { + $languageExpansion = $this->languageParentFieldName && isset($values['uid']); $constraints = []; foreach ($values as $fieldName => $fieldValue) { diff --git a/typo3/sysext/core/Classes/Routing/Aspect/PersistenceDelegate.php b/typo3/sysext/core/Classes/Routing/Aspect/PersistenceDelegate.php index a0feffeb14a3b52b6d4dc29ee911c66122acbd25..b31b9a75e07279777a40ce0900f3ea9d019409ad 100644 --- a/typo3/sysext/core/Classes/Routing/Aspect/PersistenceDelegate.php +++ b/typo3/sysext/core/Classes/Routing/Aspect/PersistenceDelegate.php @@ -21,6 +21,8 @@ use TYPO3\CMS\Core\Database\Query\QueryBuilder; /** * Delegate implementation in order to retrieve and generate values * using a database connection. + * + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 */ class PersistenceDelegate implements DelegateInterface { diff --git a/typo3/sysext/core/Classes/Routing/Legacy/PersistedAliasMapperLegacyTrait.php b/typo3/sysext/core/Classes/Routing/Legacy/PersistedAliasMapperLegacyTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..735ef91c9f00ff1a90529fef4a8129a7638d977a --- /dev/null +++ b/typo3/sysext/core/Classes/Routing/Legacy/PersistedAliasMapperLegacyTrait.php @@ -0,0 +1,70 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Core\Routing\Legacy; + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Routing\Aspect\PersistenceDelegate; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +trait PersistedAliasMapperLegacyTrait +{ + /** + * @var PersistenceDelegate + */ + protected $persistenceDelegate; + + /** + * @return PersistenceDelegate + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 + */ + protected function getPersistenceDelegate(): PersistenceDelegate + { + if ($this->persistenceDelegate !== null) { + return $this->persistenceDelegate; + } + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($this->tableName) + ->from($this->tableName); + // @todo Restrictions (Hidden? Workspace?) + + $resolveModifier = function (QueryBuilder $queryBuilder, array $values) { + return $queryBuilder->select(...$this->persistenceFieldNames)->where( + ...$this->createFieldConstraints($queryBuilder, $values) + ); + }; + $generateModifier = function (QueryBuilder $queryBuilder, array $values) { + return $queryBuilder->select(...$this->persistenceFieldNames)->where( + ...$this->createFieldConstraints($queryBuilder, $values) + ); + }; + + return $this->persistenceDelegate = new PersistenceDelegate( + $queryBuilder, + $resolveModifier, + $generateModifier + ); + } + + /** + * @param QueryBuilder $queryBuilder + * @param array $values + * @return array + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 + */ + protected function createFieldConstraints(QueryBuilder $queryBuilder, array $values): array + { + $constraints = []; + foreach ($values as $fieldName => $fieldValue) { + $constraints[] = $queryBuilder->expr()->eq( + $fieldName, + $queryBuilder->createNamedParameter( + $fieldValue, + \PDO::PARAM_STR + ) + ); + } + return $constraints; + } +} diff --git a/typo3/sysext/core/Classes/Routing/Legacy/PersistedPatternMapperLegacyTrait.php b/typo3/sysext/core/Classes/Routing/Legacy/PersistedPatternMapperLegacyTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..c33b8603d5bbc4beb19e8c23d692e9c58a2bfb02 --- /dev/null +++ b/typo3/sysext/core/Classes/Routing/Legacy/PersistedPatternMapperLegacyTrait.php @@ -0,0 +1,93 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Core\Routing\Legacy; + +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\QueryBuilder; +use TYPO3\CMS\Core\Routing\Aspect\PersistenceDelegate; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +trait PersistedPatternMapperLegacyTrait +{ + /** + * @var PersistenceDelegate + */ + protected $persistenceDelegate; + + /** + * @return PersistenceDelegate + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 + */ + protected function getPersistenceDelegate(): PersistenceDelegate + { + if ($this->persistenceDelegate !== null) { + return $this->persistenceDelegate; + } + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable($this->tableName) + ->from($this->tableName); + // @todo Restrictions (Hidden? Workspace?) + + $resolveModifier = function (QueryBuilder $queryBuilder, array $values) { + return $queryBuilder->select('*')->where( + ...$this->createRouteFieldConstraints($queryBuilder, $values, true) + ); + }; + $generateModifier = function (QueryBuilder $queryBuilder, array $values) { + return $queryBuilder->select('*')->where( + ...$this->createRouteFieldConstraints($queryBuilder, $values) + ); + }; + + return $this->persistenceDelegate = new PersistenceDelegate( + $queryBuilder, + $resolveModifier, + $generateModifier + ); + } + + /** + * @param QueryBuilder $queryBuilder + * @param array $values + * @param bool $resolveExpansion + * @return array + * @deprecated since TYPO3 v10.3, will be removed in TYPO3 v11.0 + */ + protected function createRouteFieldConstraints( + QueryBuilder $queryBuilder, + array $values, + bool $resolveExpansion = false + ): array { + $languageExpansion = $this->languageParentFieldName + && $resolveExpansion + && isset($values['uid']); + + $constraints = []; + foreach ($values as $fieldName => $fieldValue) { + if ($languageExpansion && $fieldName === 'uid') { + continue; + } + $constraints[] = $queryBuilder->expr()->eq( + $fieldName, + $queryBuilder->createNamedParameter( + $fieldValue, + \PDO::PARAM_STR + ) + ); + } + // If requested, either match uid or language parent field value + if ($languageExpansion) { + $idParameter = $queryBuilder->createNamedParameter( + $values['uid'], + \PDO::PARAM_INT + ); + $constraints[] = $queryBuilder->expr()->orX( + $queryBuilder->expr()->eq('uid', $idParameter), + $queryBuilder->expr()->eq($this->languageParentFieldName, $idParameter) + ); + } + + return $constraints; + } +}