diff --git a/Classes/DataProcessing/ContainerProcessor.php b/Classes/DataProcessing/ContainerProcessor.php
index 242816df..2e8d87a2 100644
--- a/Classes/DataProcessing/ContainerProcessor.php
+++ b/Classes/DataProcessing/ContainerProcessor.php
@@ -110,11 +110,7 @@ protected function processColPos(
'tables' => 'tt_content'
];
foreach ($children as &$child) {
- if ($child['t3ver_oid'] > 0) {
- $conf['source'] = $child['t3ver_oid'];
- } else {
- $conf['source'] = $child['uid'];
- }
+ $conf['source'] = $child['uid'];
$child['renderedContent'] = $cObj->render($contentRecordRenderer, $conf);
}
$processedData[$as] = $children;
diff --git a/Classes/Domain/Factory/ContainerFactory.php b/Classes/Domain/Factory/ContainerFactory.php
index 325a1832..eb12597c 100644
--- a/Classes/Domain/Factory/ContainerFactory.php
+++ b/Classes/Domain/Factory/ContainerFactory.php
@@ -32,14 +32,18 @@ class ContainerFactory implements SingletonInterface
protected $tcaRegistry;
/**
- * ContainerFactory constructor.
- * @param Database|null $database
- * @param Registry|null $tcaRegistry
+ * @var int
*/
- public function __construct(Database $database = null, Registry $tcaRegistry = null)
+ protected $workspaceId = 0;
+
+ public function __construct(Database $database = null, Registry $tcaRegistry = null, Context $context = null)
{
$this->database = $database ?? GeneralUtility::makeInstance(Database::class);
$this->tcaRegistry = $tcaRegistry ?? GeneralUtility::makeInstance(Registry::class);
+ if ($context === null) {
+ $context = GeneralUtility::makeInstance(Context::class);
+ }
+ $this->workspaceId = (int)$context->getPropertyFromAspect('workspace', 'id');
}
/**
@@ -77,6 +81,7 @@ public function buildContainer(int $uid): Container
} else {
// connected mode
$defaultRecords = $this->database->fetchRecordsByParentAndLanguage($defaultRecord['uid'], 0);
+ $defaultRecords = $this->doWorkspaceOverlay($defaultRecords);
$localizedRecords = $this->database->fetchOverlayRecords($defaultRecords, $language);
$childRecords = $this->sortLocalizedRecordsByDefaultRecords($defaultRecords, $localizedRecords);
}
@@ -100,24 +105,20 @@ public function buildContainer(int $uid): Container
*/
protected function doWorkspaceOverlay(array $defaultRecords): array
{
- $workspaceId = GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'id');
- if ($workspaceId > 0) {
- $workspaceRecords = $this->database->fetchWorkspaceRecords($defaultRecords, $workspaceId);
- $overlayed = [];
+ if (empty($defaultRecords)) {
+ return [];
+ }
+ if ($this->workspaceId > 0) {
+ $filtered = [];
+ $uidsHavingWorkspaceVersion = $this->database->fetchUidsHavingWorkspaceVersion($defaultRecords, $this->workspaceId);
foreach ($defaultRecords as $defaultRecord) {
- $foundOverlay = null;
- foreach ($workspaceRecords as $workspaceRecord) {
- if ($workspaceRecord['t3ver_oid'] === $defaultRecord['uid']) {
- $foundOverlay = $workspaceRecord;
- }
- }
- if ($foundOverlay !== null) {
- $overlayed[] = $foundOverlay;
- } else {
- $overlayed[] = $defaultRecord;
+ if ($defaultRecord['t3ver_wsid'] === $this->workspaceId) {
+ $filtered[] = $defaultRecord;
+ } elseif (in_array($defaultRecord['uid'], $uidsHavingWorkspaceVersion, true) === false) {
+ $filtered[] = $defaultRecord;
}
}
- return $overlayed;
+ return $filtered;
}
// filter workspace placeholders
$filtered = [];
@@ -164,6 +165,7 @@ protected function buildContainerWithOverlay(int $uid, LanguageAspect $languageA
// connected mode
$childRecords = $this->database->fetchRecordsByParentAndLanguage($defaultRecord['uid'], 0);
if ($languageAspect->doOverlays()) {
+ $childRecords = $this->doWorkspaceOverlay($childRecords);
$childRecordsOverlays = $this->database->fetchOverlayRecords($childRecords, $language);
$childRecords = $this->doOverlay($childRecords, $childRecordsOverlays);
}
@@ -171,6 +173,7 @@ protected function buildContainerWithOverlay(int $uid, LanguageAspect $languageA
} else {
$childRecords = $this->database->fetchRecordsByParentAndLanguage($record['uid'], 0);
if ($languageAspect->doOverlays()) {
+ $childRecords = $this->doWorkspaceOverlay($childRecords);
$childRecordsOverlays = $this->database->fetchOverlayRecords($childRecords, $language);
$childRecords = $this->doOverlay($childRecords, $childRecordsOverlays);
}
@@ -196,7 +199,9 @@ protected function sortLocalizedRecordsByDefaultRecords(array $defaultRecords, a
$sorted = [];
foreach ($defaultRecords as $defaultRecord) {
foreach ($localizedRecords as $localizedRecord) {
- if ($localizedRecord['l18n_parent'] === $defaultRecord['uid']) {
+ if ($localizedRecord['l18n_parent'] === $defaultRecord['uid'] ||
+ $localizedRecord['l18n_parent'] === $defaultRecord['t3ver_oid']
+ ) {
$sorted[] = $localizedRecord;
}
}
@@ -215,7 +220,9 @@ protected function doOverlay(array $defaultRecords, array $localizedRecords): ar
foreach ($defaultRecords as $defaultRecord) {
$foundOverlay = null;
foreach ($localizedRecords as $localizedRecord) {
- if ($localizedRecord['l18n_parent'] === $defaultRecord['uid']) {
+ if ($localizedRecord['l18n_parent'] === $defaultRecord['uid'] ||
+ $localizedRecord['l18n_parent'] === $defaultRecord['t3ver_oid']
+ ) {
$foundOverlay = $localizedRecord;
}
}
diff --git a/Classes/Domain/Factory/Database.php b/Classes/Domain/Factory/Database.php
index 5f1bc047..bef7d445 100644
--- a/Classes/Domain/Factory/Database.php
+++ b/Classes/Domain/Factory/Database.php
@@ -12,16 +12,37 @@
* of the License, or any later version.
*/
+use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer;
+use TYPO3\CMS\Core\Database\Query\Restriction\FrontendWorkspaceRestriction;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Versioning\VersionState;
class Database implements SingletonInterface
{
+ /**
+ * @var int
+ */
+ protected $backendUserId = 0;
+
+ /**
+ * @var int
+ */
+ protected $workspaceId = 0;
+
+ public function __construct(Context $context = null)
+ {
+ if ($context === null) {
+ $context = GeneralUtility::makeInstance(Context::class);
+ }
+ $this->backendUserId = (int)$context->getPropertyFromAspect('backend.user', 'id', 0);
+ $this->workspaceId = (int)$context->getPropertyFromAspect('workspace', 'id');
+ }
/**
* @return QueryBuilder
@@ -31,8 +52,11 @@ protected function getQueryBuilder(): QueryBuilder
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
if (TYPO3_MODE === 'BE') {
$queryBuilder->getRestrictions()->removeAll()->add(GeneralUtility::makeInstance(DeletedRestriction::class));
- } else {
+ } elseif (TYPO3_MODE === 'FE') {
$queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class));
+ if ($this->backendUserId > 0) {
+ $queryBuilder->getRestrictions()->removeByType(FrontendWorkspaceRestriction::class);
+ }
}
return $queryBuilder;
}
@@ -91,7 +115,8 @@ public function fetchOneDefaultRecord(array $record): ?array
public function fetchRecordsByParentAndLanguage(int $parent, int $language): array
{
$queryBuilder = $this->getQueryBuilder();
- $records = (array)$queryBuilder->select('*')
+
+ return (array)$queryBuilder->select('*')
->from('tt_content')
->where(
$queryBuilder->expr()->eq(
@@ -102,15 +127,21 @@ public function fetchRecordsByParentAndLanguage(int $parent, int $language): arr
'sys_language_uid',
$queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
),
- $queryBuilder->expr()->eq(
- 't3ver_oid',
- $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+ $queryBuilder->expr()->notIn(
+ 't3ver_state',
+ $queryBuilder->createNamedParameter(
+ [VersionState::NEW_PLACEHOLDER, VersionState::MOVE_PLACEHOLDER],
+ Connection::PARAM_INT_ARRAY
+ )
+ ),
+ $queryBuilder->expr()->in(
+ 't3ver_wsid',
+ $queryBuilder->createNamedParameter([0, $this->workspaceId], Connection::PARAM_INT_ARRAY)
)
)
->orderBy('sorting', 'ASC')
->execute()
->fetchAll();
- return $records;
}
/**
@@ -123,6 +154,9 @@ public function fetchOverlayRecords(array $records, int $language): array
$uids = [];
foreach ($records as $record) {
$uids[] = $record['uid'];
+ if ($record['t3ver_oid'] > 0) {
+ $uids[] = $record['t3ver_oid'];
+ }
}
$queryBuilder = $this->getQueryBuilder();
$records = (array)$queryBuilder->select('*')
@@ -136,30 +170,34 @@ public function fetchOverlayRecords(array $records, int $language): array
'sys_language_uid',
$queryBuilder->createNamedParameter($language, \PDO::PARAM_INT)
),
- $queryBuilder->expr()->eq(
- 't3ver_oid',
- $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+ $queryBuilder->expr()->notIn(
+ 't3ver_state',
+ $queryBuilder->createNamedParameter(
+ [VersionState::NEW_PLACEHOLDER, VersionState::MOVE_PLACEHOLDER],
+ Connection::PARAM_INT_ARRAY
+ )
+ ),
+ $queryBuilder->expr()->in(
+ 't3ver_wsid',
+ $queryBuilder->createNamedParameter([0, $this->workspaceId], Connection::PARAM_INT_ARRAY)
)
)
->execute()
->fetchAll();
-
return $records;
}
- /**
- * @param array $records
- * @param int $workspaceId
- * @return array
- */
- public function fetchWorkspaceRecords(array $records, int $workspaceId): array
+ public function fetchUidsHavingWorkspaceVersion(array $records, int $workspaceId): array
{
+ if (empty($records)) {
+ return [];
+ }
$uids = [];
foreach ($records as $record) {
$uids[] = $record['uid'];
}
$queryBuilder = $this->getQueryBuilder();
- $records = (array)$queryBuilder->select('*')
+ return (array)$queryBuilder->select('t3ver_oid')
->from('tt_content')
->where(
$queryBuilder->expr()->in(
@@ -172,8 +210,7 @@ public function fetchWorkspaceRecords(array $records, int $workspaceId): array
)
)
->execute()
- ->fetchAll();
- return $records;
+ ->fetchAll(\PDO::FETCH_COLUMN);
}
/**
diff --git a/Classes/Hooks/Datahandler/Database.php b/Classes/Hooks/Datahandler/Database.php
index aaed1c7a..ca4bb12a 100644
--- a/Classes/Hooks/Datahandler/Database.php
+++ b/Classes/Hooks/Datahandler/Database.php
@@ -55,6 +55,29 @@ public function fetchOneRecord(int $uid): ?array
return $record;
}
+ /**
+ * @param int $uid
+ * @return array|null
+ */
+ public function fetchOneMovedRecord(int $uid): ?array
+ {
+ $queryBuilder = $this->getQueryBuilder();
+ $record = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3ver_move_id',
+ $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetch();
+ if ($record === false) {
+ return null;
+ }
+ return $record;
+ }
+
/**
* @param array $record
* @return array
diff --git a/Classes/Hooks/Datahandler/DatamapAfterDatabaseOperationHook.php b/Classes/Hooks/Datahandler/DatamapAfterDatabaseOperationHook.php
index 5fe19bf1..f6071716 100644
--- a/Classes/Hooks/Datahandler/DatamapAfterDatabaseOperationHook.php
+++ b/Classes/Hooks/Datahandler/DatamapAfterDatabaseOperationHook.php
@@ -12,13 +12,24 @@
* of the License, or any later version.
*/
-use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\DataHandling\DataHandler;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
class DatamapAfterDatabaseOperationHook
{
+ /**
+ * @var Database
+ */
+ protected $database;
+
+ /**
+ * @param Database|null $database
+ */
+ public function __construct(Database $database = null)
+ {
+ $this->database = $database ?? GeneralUtility::makeInstance(Database::class);
+ }
/**
* @param string $status
@@ -33,19 +44,35 @@ public function processDatamap_afterDatabaseOperations(string $status, string $t
if (
$table === 'tt_content' &&
$status === 'update' &&
+ $dataHandler->BE_USER->workspace > 0 &&
MathUtility::canBeInterpretedAsInteger($id) &&
is_array($dataHandler->datamap['tt_content'])
) {
$datamapForPlaceHolders = ['tt_content' => []];
foreach ($dataHandler->datamap['tt_content'] as $origId => $data) {
if (!empty($data['tx_container_parent']) && $data['tx_container_parent'] > 0) {
- $workspaceVersion = BackendUtility::getWorkspaceVersionOfRecord($dataHandler->BE_USER->workspace, $table, $origId, 'uid,t3ver_oid');
- if ((int)$workspaceVersion['uid'] === (int)$id && (int)$workspaceVersion['uid'] !== (int)$origId) {
+ $origRecord = $this->database->fetchOneRecord((int)$origId);
+ // origRecord is copied placeholder
+ if (
+ (int)$origRecord['t3ver_oid'] === 0 &&
+ (int)$origRecord['tx_container_parent'] !== (int)$data['tx_container_parent'] &&
+ (int)$origRecord['t3ver_wsid'] === (int)$dataHandler->BE_USER->workspace
+ ) {
$datamapForPlaceHolders['tt_content'][$origId] = ['tx_container_parent' => $data['tx_container_parent']];
+ } else {
+ // origRecord is moved placehoder
+ $origRecord = $this->database->fetchOneMovedRecord((int)$origId);
+ if (
+ (int)$origRecord['t3ver_oid'] === 0 &&
+ (int)$origRecord['tx_container_parent'] !== (int)$data['tx_container_parent'] &&
+ (int)$origRecord['t3ver_wsid'] === (int)$dataHandler->BE_USER->workspace
+ ) {
+ $datamapForPlaceHolders['tt_content'][$origRecord['uid']] = ['tx_container_parent' => $data['tx_container_parent']];
+ }
}
}
}
- if (count($datamapForPlaceHolders['tt_content']) > 0) {
+ if (!empty($datamapForPlaceHolders['tt_content'])) {
$localDataHandler = GeneralUtility::makeInstance(DataHandler::class);
$localDataHandler->bypassWorkspaceRestrictions = true;
$localDataHandler->start($datamapForPlaceHolders, [], $dataHandler->BE_USER);
diff --git a/Tests/Functional/Datahandler/Workspace/ContainerTest.php b/Tests/Functional/Datahandler/Workspace/ContainerTest.php
index 1bf10c4c..803a09b4 100644
--- a/Tests/Functional/Datahandler/Workspace/ContainerTest.php
+++ b/Tests/Functional/Datahandler/Workspace/ContainerTest.php
@@ -25,6 +25,7 @@ protected function setUp(): void
parent::setUp();
$this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/pages.xml');
$this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/tt_content_default_language.xml');
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/tt_content_default_language_second_container.xml');
$this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/Workspace/sys_workspace.xml');
$this->backendUser->setWorkspace(1);
}
@@ -63,6 +64,331 @@ public function newVersionDoesNotCreateNewVersionsOfChildren(): void
self::assertFalse($row);
}
+ /**
+ * @test
+ */
+ public function moveChildsColPosInContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'move' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => '1-201',
+ 'sys_language_uid' => 0
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // moved record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->orWhere(
+ $queryBuilder->expr()->eq(
+ 't3ver_move_id',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(2, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(201, $row['colPos']);
+ }
+ }
+
+ /**
+ * @test
+ */
+ public function moveChildOutsideContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'move' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => 0,
+ 'sys_language_uid' => 0
+
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // moved record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->orWhere(
+ $queryBuilder->expr()->eq(
+ 't3ver_move_id',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(2, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(0, $row['tx_container_parent']);
+ self::assertSame(0, $row['colPos']);
+ }
+ }
+
+ /**
+ * @test
+ */
+ public function copyChildsColPosInContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'copy' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => '1-201',
+ 'sys_language_uid' => 0
+
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // moved record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(2, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(201, $row['colPos']);
+ }
+ }
+
+ /**
+ * @test
+ */
+ public function copyChildOutsideContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'copy' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => 0,
+ 'sys_language_uid' => 0
+
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // copied record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ ),
+ $queryBuilder->expr()->eq(
+ 't3ver_oid',
+ $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(1, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(0, $row['colPos']);
+ }
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ ),
+ $queryBuilder->expr()->neq(
+ 't3ver_oid',
+ $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(1, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(0, $row['tx_container_parent']);
+ self::assertSame(0, $row['colPos']);
+ }
+ }
+
+ /**
+ * @test
+ */
+ public function copyChildsColPosInOtherContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'copy' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => '91-201',
+ 'sys_language_uid' => 0
+
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // copied record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(2, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(91, $row['tx_container_parent']);
+ self::assertSame(201, $row['colPos']);
+ }
+ }
+
+ /**
+ * @test
+ */
+ public function moveChildsColPosInOtherContainer(): void
+ {
+ $cmdmap = [
+ 'tt_content' => [
+ 2 => [
+ 'move' => [
+ 'action' => 'paste',
+ 'target' => 3,
+ 'update' => [
+ 'colPos' => '91-201',
+ 'sys_language_uid' => 0
+
+ ]
+ ]
+ ]
+ ]
+ ];
+ $this->dataHandler->start([], $cmdmap, $this->backendUser);
+ $this->dataHandler->process_cmdmap();
+
+ // copied record is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
+ $queryBuilder = $this->getQueryBuilder();
+ $rows = $queryBuilder->select('*')
+ ->from('tt_content')
+ ->where(
+ $queryBuilder->expr()->eq(
+ 't3_origuid',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->orWhere(
+ $queryBuilder->expr()->eq(
+ 't3ver_move_id',
+ $queryBuilder->createNamedParameter(2, \PDO::PARAM_INT)
+ )
+ )
+ ->execute()
+ ->fetchAll();
+ self::assertSame(2, count($rows));
+ foreach ($rows as $row) {
+ self::assertSame(1, $row['t3ver_wsid']);
+ self::assertSame(91, $row['tx_container_parent']);
+ self::assertSame(201, $row['colPos']);
+ }
+ }
+
/**
* @test
*/
@@ -84,6 +410,11 @@ public function copyContainer(): void
$this->dataHandler->start([], $cmdmap, $this->backendUser);
$this->dataHandler->process_cmdmap();
+ // copied child is not modified
+ $row = $this->fetchOneRecord('uid', 2);
+ self::assertSame(1, $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
+
$queryBuilder = $this->getQueryBuilder();
$containerRow = $queryBuilder->select('*')
->from('tt_content')
@@ -111,9 +442,11 @@ public function copyContainer(): void
)
->execute()
->fetchAll();
+ self::assertSame(2, count($rows));
foreach ($rows as $row) {
self::assertSame(1, $row['t3ver_wsid']);
self::assertSame($containerRow['uid'], $row['tx_container_parent']);
+ self::assertSame(200, $row['colPos']);
}
}
}
diff --git a/Tests/Functional/Domain/Factory/ContainerFactoryTest.php b/Tests/Functional/Domain/Factory/ContainerFactoryTest.php
index f15208c4..aee9e1ed 100644
--- a/Tests/Functional/Domain/Factory/ContainerFactoryTest.php
+++ b/Tests/Functional/Domain/Factory/ContainerFactoryTest.php
@@ -11,6 +11,9 @@
*/
use B13\Container\Domain\Factory\ContainerFactory;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\LanguageAspect;
+use TYPO3\CMS\Core\Context\WorkspaceAspect;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
@@ -43,4 +46,86 @@ public function localizedContainerChildElementsHasSortingOfDefaultChildElements(
$first = $children[0];
self::assertSame(6, $first['uid']);
}
+
+ /**
+ * @test
+ */
+ public function containerHoldsMovedChildrenInWorkspaceClipboard(): void
+ {
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/Workspace/sys_workspace.xml');
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceClipboard.xml');
+ $workspaceAspect = GeneralUtility::makeInstance(WorkspaceAspect::class, 1);
+ GeneralUtility::makeInstance(Context::class)->setAspect('workspace', $workspaceAspect);
+ $containerFactory = GeneralUtility::makeInstance(ContainerFactory::class);
+ $container = $containerFactory->buildContainer(101);
+ $children = $container->getChildrenByColPos(200);
+ self::assertSame(0, count($children));
+ $container = $containerFactory->buildContainer(103);
+ $children = $container->getChildrenByColPos(201);
+ self::assertSame(1, count($children));
+ $first = $children[0];
+ self::assertSame(104, $first['uid']);
+ }
+
+ /**
+ * @test
+ */
+ public function containerHoldsMovedChildrenInWorkspaceAjax(): void
+ {
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/Workspace/sys_workspace.xml');
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceAjax.xml');
+ $workspaceAspect = GeneralUtility::makeInstance(WorkspaceAspect::class, 1);
+ GeneralUtility::makeInstance(Context::class)->setAspect('workspace', $workspaceAspect);
+ $containerFactory = GeneralUtility::makeInstance(ContainerFactory::class);
+ $container = $containerFactory->buildContainer(101);
+ $children = $container->getChildrenByColPos(200);
+ self::assertSame(0, count($children));
+ $container = $containerFactory->buildContainer(103);
+ $children = $container->getChildrenByColPos(201);
+ self::assertSame(1, count($children));
+ $first = $children[0];
+ self::assertSame(104, $first['uid']);
+ }
+
+ /**
+ * @test
+ */
+ public function containerHoldsMovedChildrenInWorkspaceWithTranslation(): void
+ {
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/Workspace/sys_workspace.xml');
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceWithTranslation.xml');
+ $workspaceAspect = GeneralUtility::makeInstance(WorkspaceAspect::class, 1);
+ $languageAspect = GeneralUtility::makeInstance(LanguageAspect::class, 1);
+ GeneralUtility::makeInstance(Context::class)->setAspect('workspace', $workspaceAspect);
+ GeneralUtility::makeInstance(Context::class)->setAspect('language', $languageAspect);
+ $containerFactory = GeneralUtility::makeInstance(ContainerFactory::class);
+ $container = $containerFactory->buildContainer(106);
+ $children = $container->getChildrenByColPos(200);
+ self::assertSame(0, count($children));
+ $container = $containerFactory->buildContainer(104);
+ $children = $container->getChildrenByColPos(202);
+ self::assertSame(1, count($children));
+ $first = $children[0];
+ self::assertSame(110, $first['uid']);
+ }
+
+ /**
+ * @test
+ */
+ public function containerHoldsCopiedChildrenInWorkspaceAjax(): void
+ {
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Fixtures/Workspace/sys_workspace.xml');
+ $this->importDataSet(ORIGINAL_ROOT . 'typo3conf/ext/container/Tests/Functional/Domain/Factory/Fixture/copiedChildrenInWorkspace.xml');
+ $workspaceAspect = GeneralUtility::makeInstance(WorkspaceAspect::class, 1);
+ GeneralUtility::makeInstance(Context::class)->setAspect('workspace', $workspaceAspect);
+ $containerFactory = GeneralUtility::makeInstance(ContainerFactory::class);
+ $container = $containerFactory->buildContainer(101);
+ $children = $container->getChildrenByColPos(200);
+ self::assertSame(1, count($children));
+ $container = $containerFactory->buildContainer(103);
+ $children = $container->getChildrenByColPos(201);
+ self::assertSame(1, count($children));
+ $first = $children[0];
+ self::assertSame(105, $first['uid']);
+ }
}
diff --git a/Tests/Functional/Domain/Factory/Fixture/copiedChildrenInWorkspace.xml b/Tests/Functional/Domain/Factory/Fixture/copiedChildrenInWorkspace.xml
new file mode 100644
index 00000000..378899af
--- /dev/null
+++ b/Tests/Functional/Domain/Factory/Fixture/copiedChildrenInWorkspace.xml
@@ -0,0 +1,37 @@
+
+
+
+ 101
+ 1
+ b13-2cols-with-header-container
+
+
+ 102
+ 1
+ 200
+ 101
+
+
+ 103
+ 1
+ b13-2cols-with-header-container
+
+
+ 104
+ 1
+ 201
+ 103
+ 1
+ 0
+ 1
+
+
+ 105
+ 1
+ 201
+ 103
+ 1
+ 104
+ -1
+
+
diff --git a/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceAjax.xml b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceAjax.xml
new file mode 100644
index 00000000..3aa73c80
--- /dev/null
+++ b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceAjax.xml
@@ -0,0 +1,28 @@
+
+
+
+ 101
+ 1
+ b13-2cols-with-header-container
+
+
+ 102
+ 1
+ 200
+ 101
+
+
+ 103
+ 1
+ b13-2cols-with-header-container
+
+
+ 104
+ 1
+ 201
+ 103
+ 1
+ 102
+ 0
+
+
diff --git a/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceClipboard.xml b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceClipboard.xml
new file mode 100644
index 00000000..774032ce
--- /dev/null
+++ b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceClipboard.xml
@@ -0,0 +1,37 @@
+
+
+
+ 101
+ 1
+ b13-2cols-with-header-container
+
+
+ 102
+ 1
+ 200
+ 101
+
+
+ 103
+ 1
+ b13-2cols-with-header-container
+
+
+ 104
+ 1
+ 201
+ 103
+ 1
+ 102
+ 4
+
+
+ 105
+ 1
+ 201
+ 103
+ 1
+ 0
+ 3
+
+
diff --git a/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceWithTranslation.xml b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceWithTranslation.xml
new file mode 100644
index 00000000..e4d8ac11
--- /dev/null
+++ b/Tests/Functional/Domain/Factory/Fixture/movedChildrenInWorkspaceWithTranslation.xml
@@ -0,0 +1,67 @@
+
+
+
+ 101
+ 1
+ b13-2cols-with-header-container
+
+
+ 102
+ 1
+ b13-2cols-with-header-container
+
+
+ 103
+ 1
+ 200
+ 102
+
+
+
+ 104
+ 1
+ 1
+ 101
+ b13-2cols-with-header-container
+
+
+ 105
+ 1
+ 200
+ 103
+ 102
+ 1
+
+
+ 106
+ 1
+ b13-2cols-with-header-container
+ 1
+ 102
+
+
+
+
+ 109
+ 1
+ 202
+ 101
+ 1
+ 103
+ 0
+
+
+
+ 110
+ 1
+ 202
+ 101
+ 1
+ 105
+ 0
+ 103
+ 1
+
+
+
+