Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions Classes/Hooks/Datahandler/CommandMapPostProcessingHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use B13\Container\Domain\Factory\ContainerFactory;
use B13\Container\Domain\Factory\Exception;
use B13\Container\Domain\Service\ContainerService;
use B13\Container\Tca\Registry;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler;
Expand All @@ -24,8 +25,11 @@
#[Autoconfigure(public: true)]
class CommandMapPostProcessingHook
{
public function __construct(protected ContainerFactory $containerFactory, protected ContainerService $containerService)
{
public function __construct(
protected ContainerFactory $containerFactory,
protected ContainerService $containerService,
protected Registry $tcaRegistry
) {
}

public function processCmdmap_postProcess(string $command, string $table, $id, $value, DataHandler $dataHandler, $pasteUpdate, $pasteDatamap): void
Expand Down Expand Up @@ -145,7 +149,17 @@ protected function copyOrMoveChildren(int $origUid, int $newId, int $containerId
&& isset($allChildren[0])
&& (int)$targetLanguage !== (int)$allChildren[0]['sys_language_uid'];
$children = [];
// the target of a column is the last child of the previous column (see
// ContainerService::getNewContentElementAtTopTargetInColumn()), so the columns have to be
// processed in the configured order: the children are ordered by sorting, and a column
// whose child has a low sorting must not be processed before the column it targets.
// children with a colPos that is not configured for the container are moved last
$colPosVals = $container->getChildrenColPos();
$availableColPosVals = $this->tcaRegistry->getAllAvailableColumnsColPos($container->getCType());
$colPosVals = array_values(array_merge(
array_intersect($availableColPosVals, $colPosVals),
array_diff($colPosVals, $availableColPosVals)
));
foreach ($colPosVals as $colPos) {
$childrenByColPos = $container->getChildrenByColPos($colPos);
if (!$chainAfterPrevious) {
Expand Down
31 changes: 31 additions & 0 deletions Tests/Functional/Datahandler/DefaultLanguage/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -414,4 +414,35 @@ public function copyContainerWithLanguageAsStringKeepsCopiedChildrenSorting(): v
$this->dataHandler->process_cmdmap();
self::assertCSVDataSet(__DIR__ . '/Fixtures/Container/CopyContainerKeepsSortingOfChildrenResult.csv');
}

/**
* children are moved column by column, the target of a column is the last child of the previous
* column. the children are fetched ordered by sorting, so if the child with the lowest sorting is
* not in the first column, the target of the following columns is a child that has not been moved
* yet and the child ends up on the source page.
*
* such a sorting is inconsistent and is reported by the container:sorting command, but it can be
* the result of copy and move operations or of an import, so a container has to be moved completely
* in that case, too.
*
* @see https://github.com/b13/container/issues/291
* @see https://github.com/b13/container/issues/738
*/
#[Test]
public function moveContainerOtherPageOnTopWithChildSortingBeforePreviousColumn(): void
{
$this->importCSVDataSet(__DIR__ . '/Fixtures/Container/MoveContainerOtherPageOnTop.csv');
// child in the second column gets a sorting lower than the children of the first column
$this->getConnectionPool()->getConnectionForTable('tt_content')->update('tt_content', ['sorting' => 96], ['uid' => 4]);
$cmdmap = [
'tt_content' => [
1 => [
'move' => 3,
],
],
];
$this->dataHandler->start([], $cmdmap, $this->backendUser);
$this->dataHandler->process_cmdmap();
self::assertCSVDataSet(__DIR__ . '/Fixtures/Container/MoveContainerOtherPageOnTopWithChildSortingBeforePreviousColumnResult.csv');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"pages"
,"uid","pid","title"
,1,0,""
,3,0,""
"tt_content"
,"uid","pid","CType","header","sorting","sys_language_uid","colPos","tx_container_parent","l18n_parent"
,1,3,"b13-2cols-with-header-container","container",256,0,0,0,0
,2,3,"header","col1-first",320,0,200,1,0
,3,3,"header","col1-second",384,0,200,1,0
,4,3,"header","col2-first",448,0,201,1,0
,10,3,"header","outside",512,0,0,0,0