Index: Classes/DataHandling/SlugHelper.php IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- Classes/DataHandling/SlugHelper.php (date 1578649322835) +++ Classes/DataHandling/SlugHelper.php (date 1578649322835) @@ -327,6 +327,50 @@ return true; } + /** + * Check if there are other records with the same slug that are located in defined pid groups. + * + * @param string $slug + * @param RecordState $state + * @return bool + * @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException + */ + public function isUniqueInGroups(string $slug, RecordState $state): bool + { + $pageId = (int)$state->resolveNodeIdentifier(); + $recordId = $state->getSubject()->getIdentifier(); + $languageId = $state->getContext()->getLanguageId(); + + if ($pageId < 0) { + $pageId = $this->resolveLivePageId($recordId); + } + + $queryBuilder = $this->createPreparedQueryBuilder(); + $this->applySlugConstraint($queryBuilder, $slug); + $relevantPids = [$pageId]; + foreach ($this->configuration["generatorOptions"]["pidGroups"] as $pidGroup) { + if (in_array($pageId, $pidGroup)) { + foreach ($pidGroup as $pid) { + if (!in_array($pid, $relevantPids)) { + $relevantPids[] = $pid; + } + } + } + } + $this->applyPageIdConstraint($queryBuilder, $relevantPids); + $this->applyRecordConstraint($queryBuilder, $recordId); + if ($languageId != -1) { + $this->applyLanguageConstraint($queryBuilder, [-1, $languageId]); + } + $this->applyWorkspaceConstraint($queryBuilder); + $statement = $queryBuilder->execute(); + + $records = $this->resolveVersionOverlays( + $statement->fetchAll() + ); + return count($records) === 0; + } + /** * Generate a slug with a suffix "/mytitle-1" if that is in use already. * @@ -380,6 +424,32 @@ return $newValue; } + /** + * Generate a slug with a suffix "/mytitle-1" if the suggested slug is in use already. + * + * @param string $slug proposed slug + * @param RecordState $state + * @return string + */ + public function buildSlugForUniqueInGroups(string $slug, RecordState $state): string + { + $slug = $this->sanitize($slug); + $rawValue = $this->extract($slug); + $newValue = $slug; + $counter = 0; + while (!$this->isUniqueInGroups( + $newValue, + $state + ) && $counter++ < 100 + ) { + $newValue = $this->sanitize($rawValue . '-' . $counter); + } + if ($counter === 100) { + $newValue = $this->sanitize($rawValue . '-' . GeneralUtility::shortMD5($rawValue)); + } + return $newValue; + } + /** * @return QueryBuilder */ @@ -478,9 +548,9 @@ /** * @param QueryBuilder $queryBuilder - * @param int $pageId + * @param int|array $pageId */ - protected function applyPageIdConstraint(QueryBuilder $queryBuilder, int $pageId) + protected function applyPageIdConstraint(QueryBuilder $queryBuilder, $pageId) { if ($pageId < 0) { throw new \RuntimeException( @@ -492,12 +562,21 @@ ); } - $queryBuilder->andWhere( - $queryBuilder->expr()->eq( - 'pid', - $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT) - ) - ); + if (is_array($pageId)) { + $queryBuilder->andWhere( + $queryBuilder->expr()->in( + 'pid', + $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT_ARRAY) + ) + ); + } else { + $queryBuilder->andWhere( + $queryBuilder->expr()->eq( + 'pid', + $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT) + ) + ); + } } /**