diff --git a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php index bc23fa0f2b301905d8f4c71c699cecaac3471e12..8fdeb49e6993030d2964a4ae2064fe52399f91c2 100644 --- a/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php +++ b/typo3/sysext/workspaces/Classes/Hook/DataHandlerHook.php @@ -610,13 +610,14 @@ class DataHandlerHook ); return; } - if (!$dataHandler->BE_USER->workspacePublishAccess($swapVersion['t3ver_wsid'])) { - $dataHandler->newlog('User could not publish records from workspace #' . $swapVersion['t3ver_wsid'], SystemLogErrorClassification::USER_ERROR); + $workspaceId = (int)$swapVersion['t3ver_wsid']; + if (!$dataHandler->BE_USER->workspacePublishAccess($workspaceId)) { + $dataHandler->newlog('User could not publish records from workspace #' . $workspaceId, SystemLogErrorClassification::USER_ERROR); return; } - $wsAccess = $dataHandler->BE_USER->checkWorkspace($swapVersion['t3ver_wsid']); - if (!($swapVersion['t3ver_wsid'] <= 0 || !($wsAccess['publish_access'] & 1) || (int)$swapVersion['t3ver_stage'] === -10)) { - $dataHandler->newlog('Records in workspace #' . $swapVersion['t3ver_wsid'] . ' can only be published when in "Publish" stage.', SystemLogErrorClassification::USER_ERROR); + $wsAccess = $dataHandler->BE_USER->checkWorkspace($workspaceId); + if (!($workspaceId <= 0 || !($wsAccess['publish_access'] & 1) || (int)$swapVersion['t3ver_stage'] === -10)) { + $dataHandler->newlog('Records in workspace #' . $workspaceId . ' can only be published when in "Publish" stage.', SystemLogErrorClassification::USER_ERROR); return; } if (!($dataHandler->doesRecordExist($table, $swapWith, Permission::PAGE_SHOW) && $dataHandler->checkRecordUpdateAccess($table, $swapWith))) { @@ -753,6 +754,8 @@ class DataHandlerHook if (!empty($sqlErrors)) { $dataHandler->newlog('During Swapping: SQL errors happened: ' . implode('; ', $sqlErrors), SystemLogErrorClassification::SYSTEM_ERROR); } else { + // Update localized elements to use the live l10n_parent now + $this->updateL10nOverlayRecordsOnPublish($table, $id, $swapWith, $workspaceId, $dataHandler); // Register swapped ids for later remapping: $this->remappedIds[$table][$id] = $swapWith; $this->remappedIds[$table][$swapWith] = $id; @@ -830,6 +833,90 @@ class DataHandlerHook } } + /** + * If an editor is doing "partial" publishing, the translated children need to be "linked" to the now pointed + * live record, as if the versioned record (which is deleted) would have never existed. + * + * This is related to the l10n_source and l10n_parent fields. + * + * This needs to happen before the hook calls DataHandler->deleteEl() otherwise the children get deleted as well. + * + * @param string $table the database table of the published record + * @param int $liveId the live version / online version of the record that was just published + * @param int $previouslyUsedVersionId the versioned record ID (wsid>0) which is about to be deleted + * @param int $workspaceId the workspace ID + * @param DataHandler $dataHandler + */ + protected function updateL10nOverlayRecordsOnPublish(string $table, int $liveId, int $previouslyUsedVersionId, int $workspaceId, DataHandler $dataHandler): void + { + if (!BackendUtility::isTableLocalizable($table)) { + return; + } + if (!BackendUtility::isTableWorkspaceEnabled($table)) { + return; + } + $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($table); + $queryBuilder = $connection->createQueryBuilder(); + $queryBuilder->getRestrictions()->removeAll(); + + $l10nParentFieldName = $GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']; + $constraints = $queryBuilder->expr()->eq( + $l10nParentFieldName, + $queryBuilder->createNamedParameter($previouslyUsedVersionId, \PDO::PARAM_INT) + ); + $translationSourceFieldName = $GLOBALS['TCA'][$table]['ctrl']['translationSource'] ?? null; + if ($translationSourceFieldName) { + $constraints = $queryBuilder->expr()->orX( + $constraints, + $queryBuilder->expr()->eq( + $translationSourceFieldName, + $queryBuilder->createNamedParameter($previouslyUsedVersionId, \PDO::PARAM_INT) + ) + ); + } + + $queryBuilder + ->select('uid', $l10nParentFieldName) + ->from($table) + ->where( + $constraints, + $queryBuilder->expr()->eq( + 't3ver_wsid', + $queryBuilder->createNamedParameter($workspaceId, \PDO::PARAM_INT) + ) + ); + + if ($translationSourceFieldName) { + $queryBuilder->addSelect($translationSourceFieldName); + } + + $statement = $queryBuilder->execute(); + while ($record = $statement->fetch()) { + $updateFields = []; + $dataTypes = [\PDO::PARAM_INT]; + if ((int)$record[$l10nParentFieldName] === $previouslyUsedVersionId) { + $updateFields[$l10nParentFieldName] = $liveId; + $dataTypes[] = \PDO::PARAM_INT; + } + if ($translationSourceFieldName && (int)$record[$translationSourceFieldName] === $previouslyUsedVersionId) { + $updateFields[$translationSourceFieldName] = $liveId; + $dataTypes[] = \PDO::PARAM_INT; + } + + if (empty($updateFields)) { + continue; + } + + $connection->update( + $table, + $updateFields, + ['uid' => (int)$record['uid']], + $dataTypes + ); + $dataHandler->updateRefIndex($table, $record['uid']); + } + } + /** * Processes fields of a record for the publishing/swapping process. * Basically this takes care of IRRE (type "inline") child references. diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSorting.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSorting.csv index b7067c4335dfa238390a2374b15c8113124fd807..0fe4125d45340527bb25bdeea511608d41f2b5dd 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSorting.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSorting.csv @@ -11,14 +11,14 @@ ,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10" ,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10" ,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2" -,323,89,384,0,1,321,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" +,323,89,384,0,1,297,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" ,324,89,576,0,1,297,0,0,1,3,0,0,301,"[MOVE-TO PLACEHOLDER for #301, WS#1]" -,325,89,448,0,2,321,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,325,89,448,0,2,297,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" ,326,89,544,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]" "sys_refindex",,,,,,,,,,,,,, ,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,, ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,, ,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",0,0,0,"be_users",3,,,,, ,"1b70a8e25c22645f7a49a79f57f3cf3f","sys_category",31,"parent",0,0,0,"sys_category",28,,,,, -,"cd92ab3ab5798dc139f98107e7c28cb7","tt_content",323,"l18n_parent",0,0,1,"tt_content",321,,,,, -,"1c8013278ae997181374e3c76322e114","tt_content",325,"l18n_parent",0,0,1,"tt_content",321,,,,, +,"cfe2297ddc6d88ee467f4104f50aba25","tt_content",323,"l18n_parent",0,0,1,"tt_content",297,,,,, +,"a254b2d44709add64b50bba7921b1e90","tt_content",325,"l18n_parent",0,0,1,"tt_content",297,,,,, diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAfterSelf.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAfterSelf.csv index e5dee0a76a94351adeed9394d2404c66e267233d..76e2c8d6e39f71b5cee4974c94e06dcac1ce801a 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAfterSelf.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAfterSelf.csv @@ -11,14 +11,14 @@ ,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10" ,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10" ,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2" -,323,89,384,0,1,321,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" +,323,89,384,0,1,297,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" ,324,89,416,0,1,297,0,0,1,3,0,0,301,"[MOVE-TO PLACEHOLDER for #301, WS#1]" -,325,89,448,0,2,321,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,325,89,448,0,2,297,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" ,326,89,480,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]" "sys_refindex",,,,,,,,,,,,,, ,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,, ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,, ,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",0,0,0,"be_users",3,,,,, ,"1b70a8e25c22645f7a49a79f57f3cf3f","sys_category",31,"parent",0,0,0,"sys_category",28,,,,, -,"cd92ab3ab5798dc139f98107e7c28cb7","tt_content",323,"l18n_parent",0,0,1,"tt_content",321,,,,, -,"1c8013278ae997181374e3c76322e114","tt_content",325,"l18n_parent",0,0,1,"tt_content",321,,,,, +,"cfe2297ddc6d88ee467f4104f50aba25","tt_content",323,"l18n_parent",0,0,1,"tt_content",297,,,,, +,"a254b2d44709add64b50bba7921b1e90","tt_content",325,"l18n_parent",0,0,1,"tt_content",297,,,,, diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv index 73a1e931c5d1abfea9ba65d794512fcaaef34154..e2a7facd45b7bf8d2284a8e3e7a75209bd015e87 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv @@ -19,9 +19,9 @@ ,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10" ,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10" ,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2" -,323,89,384,0,1,321,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" +,323,89,384,0,1,297,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" ,324,89,576,0,1,297,0,0,1,3,0,0,301,"[MOVE-TO PLACEHOLDER for #301, WS#1]" -,325,89,448,0,2,321,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,325,89,448,0,2,297,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" ,326,89,544,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]" ,327,91,256,0,0,0,0,299,1,1,0,0,0,"Regular Element #3" ,328,91,256,0,0,0,0,299,1,-1,0,327,0,"Regular Element #3" @@ -40,8 +40,8 @@ ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,, ,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",0,0,0,"be_users",3,,,,, ,"1b70a8e25c22645f7a49a79f57f3cf3f","sys_category",31,"parent",0,0,0,"sys_category",28,,,,, -,"cd92ab3ab5798dc139f98107e7c28cb7","tt_content",323,"l18n_parent",0,0,1,"tt_content",321,,,,, -,"1c8013278ae997181374e3c76322e114","tt_content",325,"l18n_parent",0,0,1,"tt_content",321,,,,, +,"cfe2297ddc6d88ee467f4104f50aba25","tt_content",323,"l18n_parent",0,0,1,"tt_content",297,,,,, +,"a254b2d44709add64b50bba7921b1e90","tt_content",325,"l18n_parent",0,0,1,"tt_content",297,,,,, ,"893ed65ba064539a74c6c86b2dd3a9ed","tt_content",330,"l18n_parent",0,0,1,"tt_content",327,,,,, ,"b3c908a26827758805d70fd387de5143","tt_content",334,"l18n_parent",0,0,1,"tt_content",331,,,,, ,"01a973226431a87669a5c5ebd9e2b351","tt_content",336,"l18n_parent",0,0,1,"tt_content",331,,,,, diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/moveContentToDifferentPageNChangeSorting.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/moveContentToDifferentPageNChangeSorting.csv index 73102960ae85c276be276e3b3a4e65e3995673a1..a488fd5223a33d4219a2d0e58e1d842d2b37e4f2 100644 --- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/moveContentToDifferentPageNChangeSorting.csv +++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/moveContentToDifferentPageNChangeSorting.csv @@ -11,14 +11,14 @@ ,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10" ,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10" ,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2" -,325,90,384,0,1,323,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" +,325,90,384,0,1,297,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1" ,326,90,160,0,1,297,0,0,1,3,0,0,301,"[MOVE-TO PLACEHOLDER for #301, WS#1]" -,327,90,448,0,2,323,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" +,327,90,448,0,2,297,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1" ,328,90,144,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]" "sys_refindex",,,,,,,,,,,,,, ,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,, ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,, ,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",0,0,0,"be_users",3,,,,, ,"1b70a8e25c22645f7a49a79f57f3cf3f","sys_category",31,"parent",0,0,0,"sys_category",28,,,,, -,"c258bb16afcf92d3ca8dd0af5ccb15db","tt_content",325,"l18n_parent",0,0,1,"tt_content",323,,,,, -,"8c7f3b6705c356900176c779bd77aff3","tt_content",327,"l18n_parent",0,0,1,"tt_content",323,,,,, +,"a254b2d44709add64b50bba7921b1e90","tt_content",325,"l18n_parent",0,0,1,"tt_content",297,,,,, +,"e5de620fdfb11e57a69c7d6aca7a7f85","tt_content",327,"l18n_parent",0,0,1,"tt_content",297,,,,,