From 85396448d27d38cec2912696b407cc6d9b47adc7 Mon Sep 17 00:00:00 2001 From: Daniel Gohlke Date: Thu, 27 Jun 2024 07:04:20 +0200 Subject: [PATCH] [BUGFIX] Fix sorting for translated content in free mode --- Classes/Command/SortingInPageCommand.php | 7 ++- Classes/Integrity/Database.php | 14 +++-- Classes/Integrity/SortingInPage.php | 4 +- ..._previous_container_on_translated_page.csv | 15 ++++++ .../Integrity/SortingInPageTest.php | 51 +++++++++++++++++++ 5 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 Tests/Functional/Integrity/Fixtures/SortingInPage/container_is_sorted_before_child_of_previous_container_on_translated_page.csv diff --git a/Classes/Command/SortingInPageCommand.php b/Classes/Command/SortingInPageCommand.php index acc736c8..f3a960ea 100644 --- a/Classes/Command/SortingInPageCommand.php +++ b/Classes/Command/SortingInPageCommand.php @@ -32,6 +32,7 @@ class SortingInPageCommand extends Command protected function configure() { $this->addArgument('pid', InputArgument::OPTIONAL, 'limit to this pid', 0); + $this->addArgument('languageId', InputArgument::OPTIONAL, 'limit to this languageId', 0); $this->addOption('apply', null, InputOption::VALUE_NONE, 'apply migration'); $this->addOption( 'enable-logging', @@ -51,13 +52,17 @@ public function execute(InputInterface $input, OutputInterface $output): int { $dryrun = $input->getOption('apply') !== true; $pid = (int)$input->getArgument('pid'); + if ($input->getArgument('languageId') !== 'all') { + $languageId = (int)$input->getArgument('languageId'); + } Bootstrap::initializeBackendAuthentication(); $GLOBALS['LANG'] = GeneralUtility::makeInstance(LanguageServiceFactory::class)->createFromUserPreferences($GLOBALS['BE_USER']); $errors = $this->sorting->run( $dryrun, $input->getOption('enable-logging'), - $pid + $pid, + $languageId, ); foreach ($errors as $error) { $output->writeln($error); diff --git a/Classes/Integrity/Database.php b/Classes/Integrity/Database.php index 22a905ca..99f19de5 100644 --- a/Classes/Integrity/Database.php +++ b/Classes/Integrity/Database.php @@ -106,7 +106,7 @@ public function getChildrenByContainerAndColPos(int $containerId, int $colPos, i return $rows; } - public function getNonContainerChildrenPerColPos(array $containerUsedColPosArray, ?int $pid = null): array + public function getNonContainerChildrenPerColPos(array $containerUsedColPosArray, ?int $pid = null, ?int $languageId = null): array { $queryBuilder = $this->getQueryBuilder(); $stm = $queryBuilder @@ -116,12 +116,18 @@ public function getNonContainerChildrenPerColPos(array $containerUsedColPosArray $queryBuilder->expr()->notIn( 'colPos', $queryBuilder->createNamedParameter($containerUsedColPosArray, Connection::PARAM_INT_ARRAY) - ), + ) + ); + + if (!is_null($languageId)) { + $stm->andWhere( $queryBuilder->expr()->eq( 'sys_language_uid', - $queryBuilder->createNamedParameter(0, Connection::PARAM_INT) + $queryBuilder->createNamedParameter($languageId, Connection::PARAM_INT) ) ); + } + if (!empty($pid)) { $stm->andWhere( $queryBuilder->expr()->eq( @@ -136,7 +142,7 @@ public function getNonContainerChildrenPerColPos(array $containerUsedColPosArray $results = $stm->executeQuery()->fetchAllAssociative(); $rows = []; foreach ($results as $result) { - $key = $result['pid'] . '-' . $result['colPos']; + $key = $result['pid'] . '-' . $result['sys_language_uid'] . '-' . $result['colPos']; if (!isset($rows[$key])) { $rows[$key] = []; } diff --git a/Classes/Integrity/SortingInPage.php b/Classes/Integrity/SortingInPage.php index efa98d10..22d3f048 100644 --- a/Classes/Integrity/SortingInPage.php +++ b/Classes/Integrity/SortingInPage.php @@ -52,7 +52,7 @@ public function __construct(Database $database, Registry $tcaRegistry, Container $this->containerService = $containerService; } - public function run(bool $dryRun = true, bool $enableLogging = false, ?int $pid = null): array + public function run(bool $dryRun = true, bool $enableLogging = false, ?int $pid = null, ?int $languageId = null): array { $this->unsetContentDefenderConfiguration(); $dataHandler = GeneralUtility::makeInstance(DataHandler::class); @@ -65,7 +65,7 @@ public function run(bool $dryRun = true, bool $enableLogging = false, ?int $pid $containerUsedColPosArray[] = $column['colPos']; } } - $rows = $this->database->getNonContainerChildrenPerColPos($containerUsedColPosArray, $pid); + $rows = $this->database->getNonContainerChildrenPerColPos($containerUsedColPosArray, $pid, $languageId); foreach ($rows as $recordsPerPageAndColPos) { $prevSorting = 0; $prevContainer = null; diff --git a/Tests/Functional/Integrity/Fixtures/SortingInPage/container_is_sorted_before_child_of_previous_container_on_translated_page.csv b/Tests/Functional/Integrity/Fixtures/SortingInPage/container_is_sorted_before_child_of_previous_container_on_translated_page.csv new file mode 100644 index 00000000..148dbfe6 --- /dev/null +++ b/Tests/Functional/Integrity/Fixtures/SortingInPage/container_is_sorted_before_child_of_previous_container_on_translated_page.csv @@ -0,0 +1,15 @@ +"pages" +,"uid","pid","sys_language_uid" +,1,0,0 +,2,1,1 +,3,1,2 +"tt_content" +,"uid","pid","colPos","CType","sorting","tx_container_parent","sys_language_uid" +,1,2,0,"b13-2cols-with-header-container",1,,1 +,2,2,0,"b13-2cols-with-header-container",2,,1 +,3,2,202,,4,1,1 +,4,2,202,,3,2,1 +,5,3,0,"b13-2cols-with-header-container",5,,2 +,6,3,0,"b13-2cols-with-header-container",6,,2 +,7,3,202,,8,5,2 +,8,3,202,,7,6,2 diff --git a/Tests/Functional/Integrity/SortingInPageTest.php b/Tests/Functional/Integrity/SortingInPageTest.php index 4c3798e8..38cbd5ee 100644 --- a/Tests/Functional/Integrity/SortingInPageTest.php +++ b/Tests/Functional/Integrity/SortingInPageTest.php @@ -65,6 +65,57 @@ public function containerIsSortedAfterChildOfPreviousContainer(): void self::assertTrue($rows[2]['sorting'] > $rows[3]['sorting'], 'container should be sorted after child of previous container'); } + public static function getPossibleTranslations(): iterable + { + yield 'with language id 1' => [ + 'languageId' => 1, + 'expected' => [ + 'errors' => 1, + 'sortings' => [ + 2 => 3, + ] + ] + ]; + yield 'with language id 2' => [ + 'languageId' => 2, + 'expected' => [ + 'errors' => 1, + 'sortings' => [ + 6 => 7, + ] + ] + ]; + yield 'with all languages' => [ + 'languageId' => null, + 'expected' => [ + 'errors' => 2, + 'sortings' => [ + 2 => 3, + 6 => 7, + ] + ] + ]; + } + + /** + * @test + * @dataProvider getPossibleTranslations + */ + public function containerIsSortedAfterChildOfPreviousContainerOnTranslatedPage(?int $languageId = null, array $expected): void + { + $this->importCSVDataSet(__DIR__ . '/Fixtures/SortingInPage/container_is_sorted_before_child_of_previous_container_on_translated_page.csv'); + $errors = $this->sorting->run(false, false, null, 0); + self::assertTrue(count($errors) === 0, 'different number of errors for default language'); + + $errors = $this->sorting->run(false, false, null, $languageId); + self::assertTrue(count($errors) === $expected['errors'], 'different number of errors for given language'); + + $rows = $this->getContentsByUid(); + foreach ($expected['sortings'] as $before => $after) { + self::assertTrue($rows[$before]['sorting'] > $rows[$after]['sorting'], 'container should be sorted after child of previous container'); + } + } + /** * @test */