Commit efa49dd7 authored by Christian Kuhn's avatar Christian Kuhn Committed by Andreas Fernandez
Browse files

[BUGFIX] Properly discard workspace MM relations

A first patch towards more reliable workspace-mm scenarios:
When a record is discarded that has mm relations, those
relations are now deleted along with the deleted "parent"
record.

Change-Id: Ic2abe8d1c828158cf86abe760aec8766abcd0e71
Resolves: #93064
Releases: master, 10.4
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67100

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent 35f6e8ba
......@@ -5333,17 +5333,52 @@ class DataHandler implements LoggerAwareInterface
$this->discard($relationRecord['table'], (int)$relationRecord['id']);
}
}
} elseif ($this->isReferenceField($fieldConfig)) {
$allowedTables = $fieldConfig['type'] === 'group' ? $fieldConfig['allowed'] : $fieldConfig['foreign_table'];
$dbAnalysis = $this->createRelationHandlerInstance();
$dbAnalysis->start($value, $allowedTables, $fieldConfig['MM'], (int)$record['uid'], $table, $fieldConfig);
foreach ($dbAnalysis->itemArray as $relationRecord) {
// @todo: Something should happen with these relations here ...
// @todo: Can't use dropReferenceIndexRowsForRecord() here, this would drop sys_refindex entries we want to keep
$this->updateRefIndex($relationRecord['table'], (int)$relationRecord['id']);
}
} elseif ($this->isReferenceField($fieldConfig) && !empty($fieldConfig['MM'])) {
$this->discardMmRelations($table, $fieldConfig, $record);
}
// @todo not inline and not mm - probably not handled correctly and has no proper test coverage yet
}
}
/**
* When a workspace record row is discarded that has mm relations, existing mm table rows need
* to be deleted. The method performs the delete operation depending on TCA field configuration.
*
* @param string $table Handled table name
* @param array $fieldConfig TCA configuration of this field
* @param array $record The full record of a left- or ride-side relation
*/
protected function discardMmRelations(string $table, array $fieldConfig, array $record): void
{
$recordUid = (int)$record['uid'];
$mmTableName = $fieldConfig['MM'];
// left - non foreign - uid_local vs. right - foreign - uid_foreign decision
$relationUidFieldName = isset($fieldConfig['MM_opposite_field']) ? 'uid_foreign' : 'uid_local';
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($mmTableName);
$queryBuilder->delete($mmTableName)->where(
// uid_local = given uid OR uid_foreign = given uid
$queryBuilder->expr()->eq($relationUidFieldName, $queryBuilder->createNamedParameter($recordUid, \PDO::PARAM_INT))
);
if ($relationUidFieldName === 'uid_foreign') {
// When discarding a local-side record - eg. sys_category - it does not matter who points to it,
// all relations can be dropped. If on foreign side - eg. tt_content to sys_category - "tablenames"
// field has to be taken into account to not delete rows with same uid from other tables.
$queryBuilder->andWhere(
$queryBuilder->expr()->eq('tablenames', $queryBuilder->createNamedParameter($table, \PDO::PARAM_STR))
);
}
if (!empty($fieldConfig['MM_table_where']) && is_string($fieldConfig['MM_table_where'])) {
$queryBuilder->andWhere(
QueryHelper::stripLogicalOperatorPrefix(str_replace('###THIS_UID###', (string)$recordUid, $fieldConfig['MM_table_where']))
);
}
$mmMatchFields = $fieldConfig['MM_match_fields'] ?? [];
foreach ($mmMatchFields as $fieldName => $fieldValue) {
$queryBuilder->andWhere(
$queryBuilder->expr()->eq($fieldName, $queryBuilder->createNamedParameter($fieldValue, \PDO::PARAM_STR))
);
}
$queryBuilder->execute();
}
/**
......
......@@ -44,9 +44,6 @@ class ActionTest extends AbstractActionTestCase
parent::addCategoryRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdFirst);
$this->assertAssertionDataSet('addCategoryRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -57,9 +54,6 @@ class ActionTest extends AbstractActionTestCase
parent::deleteCategoryRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdFirst);
$this->assertAssertionDataSet('deleteCategoryRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -70,9 +64,6 @@ class ActionTest extends AbstractActionTestCase
parent::changeCategoryRelationSorting();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdFirst);
$this->assertAssertionDataSet('changeCategoryRelationSorting');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -83,9 +74,6 @@ class ActionTest extends AbstractActionTestCase
parent::createContentAndAddRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, $this->recordIds['newContentId']);
$this->assertAssertionDataSet('createContentNAddRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -168,9 +156,6 @@ class ActionTest extends AbstractActionTestCase
parent::modifyContentOfRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdFirst);
$this->assertAssertionDataSet('modifyContentOfRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -184,9 +169,6 @@ class ActionTest extends AbstractActionTestCase
self::TABLE_Category => [self::VALUE_CategoryIdFirst],
]);
$this->assertAssertionDataSet('modifyBothsOfRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -197,9 +179,6 @@ class ActionTest extends AbstractActionTestCase
parent::deleteContentOfRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdLast);
$this->assertAssertionDataSet('deleteContentOfRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -220,9 +199,6 @@ class ActionTest extends AbstractActionTestCase
parent::copyContentOfRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, $this->recordIds['newContentId']);
$this->assertAssertionDataSet('copyContentOfRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -243,9 +219,6 @@ class ActionTest extends AbstractActionTestCase
parent::localizeContentOfRelation();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, $this->recordIds['localizedContentId']);
$this->assertAssertionDataSet('localizeContentOfRelation');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -268,9 +241,6 @@ class ActionTest extends AbstractActionTestCase
parent::moveContentOfRelationToDifferentPage();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdLast);
$this->assertAssertionDataSet('moveContentOfRelationToDifferentPage');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
/**
......@@ -283,8 +253,5 @@ class ActionTest extends AbstractActionTestCase
self::TABLE_Page => [$this->recordIds['newPageId']],
]);
$this->assertAssertionDataSet('copyPage');
// @todo: reference index not clean after this test. Needs investigation.
$this->assertCleanReferenceIndex = false;
}
}
......@@ -27,10 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,28,299,"tt_content",0,1,"categories",,,,,,,,,,,
,29,299,"tt_content",0,2,"categories",,,,,,,,,,,
,31,299,"tt_content",0,3,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,9 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,28,299,"tt_content",0,2,"categories",,,,,,,,,,,
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,297,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,9 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
,30,299,"tt_content",0,2,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,11 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
,30,299,"tt_content",0,2,"categories",,,,,,,,,,,
,28,300,"tt_content",0,1,"categories",,,,,,,,,,,
,29,300,"tt_content",0,2,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,297,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,299,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,299,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,299,"tt_content",0,1,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,299,"tt_content",0,1,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,297,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,28,299,"tt_content",0,1,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,9 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
,30,299,"tt_content",0,2,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -28,8 +28,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,297,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,9 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,29,299,"tt_content",0,1,"categories",,,,,,,,,,,
,30,299,"tt_content",0,2,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,9 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next rows should be gone
,32,299,"tt_content",0,1,"categories",,,,,,,,,,,
,29,299,"tt_content",0,2,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
......@@ -27,8 +27,6 @@
,29,297,"tt_content",0,2,"categories",,,,,,,,,,,
,29,298,"tt_content",0,1,"categories",,,,,,,,,,,
,30,298,"tt_content",0,2,"categories",,,,,,,,,,,
# @todo: next row should be gone
,32,297,"tt_content",1,0,"categories",,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","image","categories",,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1",0,2,,,,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment