Commit 2e1e235a authored by Benni Mack's avatar Benni Mack
Browse files

[!!!][TASK] Remove support for swapping instead of publishing workspace records

The functionality of "exchanging" a versioned record in a workspace with
a live version, is not used, and has certain downsides (e.g. it is not clear
what exchange happened, not event stream to understand when
was what changed, and especially when swapping single/selected items
multiple times it gets really messy). Also, swapping is conceptually
not working (when activated) for newly created records and leaves an
inconsistent state. For these reasons, the feature is dropped.

What was removed:
* The option sys_workspace.swap_modes
* The option to only swap on auto-publish
* The option to swap in workspace module

In the future it would be really beneficial to rename internal "swap"
variables to "publish" to streamline this logic.

Resolves: #92206
Releases: master
Change-Id: Ie153a890e5d0dc6ac0b8707a2739c89922e017d7
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65318


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent d53f5491
......@@ -224,7 +224,7 @@ class Backend extends Workspaces {
}
private registerEvents(): void {
$(document).on('click', '[data-action="swap"]', (e: JQueryEventObject): void => {
$(document).on('click', '[data-action="publish"]', (e: JQueryEventObject): void => {
const row = <HTMLTableRowElement>e.target.closest('tr');
this.checkIntegrity(
{
......@@ -244,15 +244,15 @@ class Backend extends Workspaces {
Wizard.setForceSelection(false);
Wizard.addSlide(
'swap-confirm',
'Swap',
TYPO3.lang['window.swap.message'],
'publish-confirm',
'Publish',
TYPO3.lang['window.publish.message'],
SeverityEnum.info,
);
Wizard.addFinalProcessingSlide((): void => {
// We passed this slide, swap the record now
// We passed this slide, publish the record now
this.sendRemoteRequest(
this.generateRemoteActionsPayload('swapSingleRecord', [
this.generateRemoteActionsPayload('publishSingleRecord', [
row.dataset.table,
row.dataset.t3ver_oid,
row.dataset.uid,
......@@ -584,10 +584,10 @@ class Backend extends Workspaces {
title: TYPO3.lang['tooltip.showChanges'],
}).append(this.getPreRenderedIcon('actions-document-info')),
this.getAction(
item.allowedAction_swap && item.Workspaces_CollectionParent === '',
'swap',
item.allowedAction_publish && item.Workspaces_CollectionParent === '',
'publish',
'actions-version-swap-version')
.attr('title', TYPO3.lang['tooltip.swap']),
.attr('title', TYPO3.lang['tooltip.publish']),
this.getAction(
item.allowedAction_view,
'preview',
......@@ -1083,16 +1083,11 @@ class Backend extends Workspaces {
*/
private renderMassActionWizard(selectedAction: string): void {
let massAction: string;
let doSwap = false;
switch (selectedAction) {
case 'publish':
massAction = 'publishWorkspace';
break;
case 'swap':
massAction = 'publishWorkspace';
doSwap = true;
break;
case 'discard':
massAction = 'flushWorkspace';
break;
......@@ -1131,8 +1126,7 @@ class Backend extends Workspaces {
init: true,
total: 0,
processed: 0,
language: this.settings.language,
swap: doSwap,
language: this.settings.language
}),
).then(sendRequestsUntilAllProcessed);
}).done((): void => {
......
......@@ -1212,25 +1212,6 @@ class BackendUserAuthentication extends AbstractUserAuthentication
return $this->checkWorkspace(0) && !($wsAccess['publish_access'] & 2);
}
/**
* Workspace swap-mode access?
*
* @return bool Returns TRUE if records can be swapped in the current workspace, otherwise FALSE
* @internal this method will be moved to EXT:workspaces
*/
public function workspaceSwapAccess()
{
// Always possible in live workspace
if ($this->workspace === 0) {
return true;
}
// In custom workspaces, only possible if swap_modes flag is not "2" (explicitly disabling swapping)
if ((int)$this->workspaceRec['swap_modes'] !== 2) {
return true;
}
return false;
}
/**
* Returns full parsed user TSconfig array, merged with TSconfig from groups.
*
......
......@@ -50,7 +50,7 @@ final class VersionState extends Enumeration
* Deleting elements is done by actually creating a
* new version of the element and setting t3ver_state=2
* that indicates the live element must be deleted upon
* swapping the versions.
* publishing the versions.
*/
const DELETE_PLACEHOLDER = 2;
......
.. include:: ../../Includes.txt
========================================================
Breaking: #92206 - Remove workspace swapping of elements
========================================================
See :issue:`92206`
Description
===========
When using workspaces, putting modified content into the live workspace has two functionality:
1. Publishing
Content is replaced with the live version, and the current live version is removed.
2. Swapping
Content is switched (swapped) with the live version, making the current live version the previously versioned content.
Especially when doing
* partial swapping
* multiple swapping
* swapping newly created content
TYPO3 will leave the workspace in an inconsistent state.
The swapping mechanism was therefore removed, leaving "Publishing" the only option to select for editors to push content from a workspace into the live website.
Impact
======
The database field and TCA option "sys_workspace.swap_modes" is removed.
The Workspace module only shows the "Publish" option anymore,
as "Swap" is removed.
The auto-publishing feature now always publishes instead of optionally swaps content.
Affected Installations
======================
TYPO3 installations which use workspaces with the swapping option
activated.
Migration
=========
All draft content is using the publishing mechanism, whereas there
is no migration needed.
.. index:: Database, TCA, NotScanned, ext:workspaces
\ No newline at end of file
......@@ -324,9 +324,6 @@
<trans-unit id="sys_workspace.disable_autocreate" resname="sys_workspace.disable_autocreate">
<source>Disable auto-versioning when editing</source>
</trans-unit>
<trans-unit id="sys_workspace.swap_modes" resname="sys_workspace.swap_modes">
<source>Swap modes</source>
</trans-unit>
<trans-unit id="sys_workspace.publish_access" resname="sys_workspace.publish_access">
<source>Publish access</source>
</trans-unit>
......
......@@ -94,7 +94,7 @@ class TreelistCacheUpdateHooks
}
/**
* Waits for DataHandler commands and looks for deleted pages or swapped pages, if found
* Waits for DataHandler commands and looks for deleted pages or published pages, if found
* further changes take place to determine whether the cache needs to be updated
*
* @param string $command The TCE command
......@@ -106,7 +106,7 @@ class TreelistCacheUpdateHooks
public function processCmdmap_postProcess($command, $table, $recordId, $commandValue, DataHandler $dataHandler)
{
$action = (is_array($commandValue) && isset($commandValue['action'])) ? (string)$commandValue['action'] : '';
if ($table === 'pages' && ($command === 'delete' || ($command === 'version' && $action === 'swap'))) {
if ($table === 'pages' && ($command === 'delete' || ($command === 'version' && $action === 'publish'))) {
$affectedRecord = BackendUtility::getRecord($table, $recordId, '*', '', false);
$affectedPageUid = $affectedRecord['uid'];
$affectedPagePid = $affectedRecord['pid'];
......@@ -116,7 +116,7 @@ class TreelistCacheUpdateHooks
if ($command === 'delete') {
$updatedFields['deleted'] = 1;
} else {
// page was published to live (swapped)
// page was published to live
$updatedFields['t3ver_wsid'] = 0;
}
$clearCacheActions = $this->determineClearCacheActions(
......
......@@ -88,12 +88,7 @@ class AutoPublishCommand extends Command
);
// Get CMD array
$cmd = $this->workspaceService->getCmdArrayForPublishWS(
$workspaceRecord['uid'],
(int)$workspaceRecord['swap_modes'] === 1
);
// $workspaceRecord['swap_modes'] == 1 means that auto-publishing will swap versions,
// not just publish and empty the workspace.
$cmd = $this->workspaceService->getCmdArrayForPublishWS($workspaceRecord['uid']);
$tce = GeneralUtility::makeInstance(DataHandler::class);
$tce->start([], $cmd);
$tce->process_cmdmap();
......@@ -120,7 +115,7 @@ class AutoPublishCommand extends Command
->add(GeneralUtility::makeInstance(DeletedRestriction::class));
return $queryBuilder
->select('uid', 'swap_modes', 'publish_time')
->select('uid', 'publish_time')
->from('sys_workspace')
->where(
$queryBuilder->expr()->eq(
......
......@@ -76,20 +76,19 @@ class ActionHandler
}
/**
* Swaps a single record.
* Publishes a single record.
*
* @param string $table
* @param int $t3ver_oid
* @param int $orig_uid
* @todo What about reporting errors back to the interface? /olly/
*/
public function swapSingleRecord($table, $t3ver_oid, $orig_uid)
public function publishSingleRecord($table, $t3ver_oid, $orig_uid)
{
$cmd = [];
$cmd[$table][$t3ver_oid]['version'] = [
'action' => 'swap',
'swapWith' => $orig_uid,
'swapIntoWS' => 1
'action' => 'publish',
'swapWith' => $orig_uid
];
$this->processTcaCmd($cmd);
}
......@@ -123,7 +122,7 @@ class ActionHandler
}
/**
* Executes an action (publish, discard, swap) to a selection set.
* Executes an action (publish, discard) to a selection set.
*
* @param \stdClass $parameter
* @return array
......@@ -138,9 +137,8 @@ class ActionHandler
}
$commands = [];
$swapIntoWorkspace = ($parameter->action === 'swap');
if ($parameter->action === 'publish' || $swapIntoWorkspace) {
$commands = $this->getPublishSwapCommands($parameter->selection, $swapIntoWorkspace);
if ($parameter->action === 'publish') {
$commands = $this->getPublishCommands($parameter->selection);
} elseif ($parameter->action === 'discard') {
$commands = $this->getFlushCommands($parameter->selection);
}
......@@ -151,20 +149,18 @@ class ActionHandler
}
/**
* Get publish swap commands
* Get publish commands
*
* @param array|\stdClass[] $selection
* @param bool $swapIntoWorkspace
* @return array
*/
protected function getPublishSwapCommands(array $selection, $swapIntoWorkspace)
protected function getPublishCommands(array $selection)
{
$commands = [];
foreach ($selection as $record) {
$commands[$record->table][$record->liveId]['version'] = [
'action' => 'swap',
'action' => 'publish',
'swapWith' => $record->versionId,
'swapIntoWS' => (bool)$swapIntoWorkspace,
];
}
return $commands;
......@@ -455,7 +451,7 @@ class ActionHandler
foreach ($items as $item) {
// Publishing uses live id in command map
if ($stageId == StagesService::STAGE_PUBLISH_EXECUTE_ID) {
$cmdMapArray[$tableName][$item->t3ver_oid]['version']['action'] = 'swap';
$cmdMapArray[$tableName][$item->t3ver_oid]['version']['action'] = 'publish';
$cmdMapArray[$tableName][$item->t3ver_oid]['version']['swapWith'] = $item->uid;
$cmdMapArray[$tableName][$item->t3ver_oid]['version']['comment'] = $comment;
$cmdMapArray[$tableName][$item->t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
......@@ -528,7 +524,7 @@ class ActionHandler
$recipients = $this->getRecipientList((array)$parameters->recipients, $parameters->additional, $setStageId);
if ($setStageId === StagesService::STAGE_PUBLISH_EXECUTE_ID) {
$cmdArray[$table][$t3ver_oid]['version']['action'] = 'swap';
$cmdArray[$table][$t3ver_oid]['version']['action'] = 'publish';
$cmdArray[$table][$t3ver_oid]['version']['swapWith'] = $uid;
$cmdArray[$table][$t3ver_oid]['version']['comment'] = $comments;
$cmdArray[$table][$t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
......@@ -617,7 +613,7 @@ class ActionHandler
}
if ($setStageId === StagesService::STAGE_PUBLISH_EXECUTE_ID) {
$cmdArray[$element->table][$element->t3ver_oid]['version']['action'] = 'swap';
$cmdArray[$element->table][$element->t3ver_oid]['version']['action'] = 'publish';
$cmdArray[$element->table][$element->t3ver_oid]['version']['swapWith'] = $element->uid;
$cmdArray[$element->table][$element->t3ver_oid]['version']['comment'] = $comments;
$cmdArray[$element->table][$element->t3ver_oid]['version']['notificationAlternativeRecipients'] = $recipients;
......
......@@ -62,9 +62,6 @@ class MassActionHandler
$publishAccess = $backendUser->workspacePublishAccess($currentWorkspace);
if ($publishAccess && !($backendUser->workspaceRec['publish_access'] & 1)) {
$actions[] = ['action' => 'publish', 'title' => $this->getLanguageService()->sL($this->pathToLocallang . ':label_doaction_publish')];
if ($backendUser->workspaceSwapAccess()) {
$actions[] = ['action' => 'swap', 'title' => $this->getLanguageService()->sL($this->pathToLocallang . ':label_doaction_swap')];
}
}
if ($currentWorkspace !== WorkspaceService::LIVE_WORKSPACE_ID) {
$actions[] = ['action' => 'discard', 'title' => $this->getLanguageService()->sL($this->pathToLocallang . ':label_doaction_discard')];
......@@ -94,7 +91,7 @@ class MassActionHandler
try {
if ($parameters->init) {
$language = $this->validateLanguageParameter($parameters);
$cnt = $this->initPublishData($this->getCurrentWorkspace(), $parameters->swap, $language);
$cnt = $this->initPublishData($this->getCurrentWorkspace(), $language);
$result['total'] = $cnt;
} else {
$result['processed'] = $this->processData();
......@@ -138,14 +135,13 @@ class MassActionHandler
* Initializes the command map to be used for publishing.
*
* @param int $workspace
* @param bool $swap
* @param int $language
* @return int
*/
protected function initPublishData($workspace, $swap, $language = null)
protected function initPublishData($workspace, $language = null)
{
// workspace might be -98 a.k.a "All Workspaces but that's save here
$publishData = $this->workspaceService->getCmdArrayForPublishWS($workspace, $swap, 0, $language);
$publishData = $this->workspaceService->getCmdArrayForPublishWS($workspace, false, 0, $language);
$recordCount = 0;
foreach ($publishData as $table => $recs) {
$recordCount += count($recs);
......
......@@ -253,7 +253,7 @@ class CommandMap
foreach ($this->commandMap as $table => $liveIdCollection) {
foreach ($liveIdCollection as $liveId => $commandCollection) {
foreach ($commandCollection as $command => $properties) {
if ($command === 'version' && isset($properties['action']) && $properties['action'] === 'swap') {
if ($command === 'version' && isset($properties['action']) && in_array($properties['action'], ['publish', 'swap'], true)) {
if (isset($properties['swapWith']) && MathUtility::canBeInterpretedAsInteger($properties['swapWith'])) {
call_user_func_array([$this, $callbackMethod], array_merge($arguments, [$table, $liveId, $properties]));
}
......@@ -635,9 +635,6 @@ class CommandMap
if (isset($elementProperties['action'])) {
$commonSwapProperties['action'] = $elementProperties['action'];
}
if (isset($elementProperties['swapIntoWS'])) {
$commonSwapProperties['swapIntoWS'] = $elementProperties['swapIntoWS'];
}
if (isset($elementProperties['comment'])) {
$commonSwapProperties['comment'] = $elementProperties['comment'];
}
......
......@@ -105,11 +105,11 @@ class DataHandlerHook
$dataHandler->versionizeRecord($table, $id, $value['label']);
break;
case 'swap':
case 'publish':
$this->version_swap(
$table,
$id,
$value['swapWith'],
(bool)$value['swapIntoWS'],
$dataHandler,
$comment,
$notificationAlternativeRecipients
......@@ -227,7 +227,7 @@ class DataHandlerHook
// In Live workspace, delete any. In other workspaces there must be match.
if ($dataHandler->BE_USER->workspace == 0 || (int)$record['t3ver_wsid'] == $dataHandler->BE_USER->workspace) {
$liveRec = BackendUtility::getLiveVersionOfRecord($table, $id, 'uid,t3ver_state');
// Processing can be skipped if a delete placeholder shall be swapped/published
// Processing can be skipped if a delete placeholder shall be published
// during the current request. Thus it will be deleted later on...
$liveRecordVersionState = VersionState::cast($liveRec['t3ver_state']);
if ($recordVersionState->equals(VersionState::DELETE_PLACEHOLDER) && !empty($liveRec['uid'])
......@@ -564,21 +564,19 @@ class DataHandlerHook
*****************************/
/**
* Swapping versions of a record
* Publishing / Swapping (= switching) versions of a record
* Version from archive (future/past, called "swap version") will get the uid of the "t3ver_oid", the official element with uid = "t3ver_oid" will get the new versions old uid. PIDs are swapped also
*
* @param string $table Table name
* @param int $id UID of the online record to swap
* @param int $swapWith UID of the archived version to swap with!
* @param bool $swapIntoWS If set, swaps online into workspace instead of publishing out of workspace.
* @param DataHandler $dataHandler DataHandler object
* @param string $comment Notification comment
* @param array $notificationAlternativeRecipients comma separated list of recipients to notify instead of normal be_users
*/
protected function version_swap($table, $id, $swapWith, bool $swapIntoWS, DataHandler $dataHandler, string $comment, $notificationAlternativeRecipients = [])
protected function version_swap($table, $id, $swapWith, DataHandler $dataHandler, string $comment, $notificationAlternativeRecipients = [])
{
// Check prerequisites before start swapping
// Check prerequisites before start publishing
// Skip records that have been deleted during the current execution
if ($dataHandler->hasDeletedRecord($table, $id)) {
return;
......@@ -626,28 +624,24 @@ class DataHandlerHook
$dataHandler->newlog('You cannot publish a record you do not have edit and show permissions for', SystemLogErrorClassification::USER_ERROR);
return;
}
if ($swapIntoWS && !$dataHandler->BE_USER->workspaceSwapAccess()) {
$dataHandler->newlog('Workspace #' . $swapVersion['t3ver_wsid'] . ' does not support swapping.', SystemLogErrorClassification::USER_ERROR);
return;
}
// Check if the swapWith record really IS a version of the original!
if (!(((int)$swapVersion['t3ver_oid'] > 0 && (int)$curVersion['t3ver_oid'] === 0) && (int)$swapVersion['t3ver_oid'] === (int)$id)) {
$dataHandler->newlog('In swap version, either t3ver_oid was not set or the t3ver_oid didn\'t match the id of the online version as it must!', SystemLogErrorClassification::SYSTEM_ERROR);
$dataHandler->newlog('In offline record, either t3ver_oid was not set or the t3ver_oid didn\'t match the id of the online version as it must!', SystemLogErrorClassification::SYSTEM_ERROR);
return;
}
// Lock file name:
$lockFileName = Environment::getVarPath() . '/lock/workspaces_swap' . $table . '_' . $id . '.json';
$lockFileName = Environment::getVarPath() . '/lock/workspaces_publish' . $table . '_' . $id . '.json';
if (@is_file($lockFileName)) {
$lockFileContents = file_get_contents($lockFileName);
$lockFileContents = json_decode($lockFileContents ?: '', true);
// Only skip if the lock file is newer than the last 1h (a publishing process should not be running longer than 60mins)
if (isset($lockFileContents['tstamp']) && $lockFileContents['tstamp'] > ($GLOBALS['EXEC_TIME']-3600)) {
$dataHandler->newlog('A swapping lock file was present. Either another swap process is already running or a previous swap process failed. Ask your administrator to handle the situation.', SystemLogErrorClassification::SYSTEM_ERROR);
$dataHandler->newlog('A publishing lock file was present. Either another publish process is already running or a previous publish process failed. Ask your administrator to handle the situation.', SystemLogErrorClassification::SYSTEM_ERROR);
return;
}
}
// Now start to swap records by first creating the lock file
// Now start to publishing records by first creating the lock file
// Write lock-file:
GeneralUtility::writeFileToTypo3tempDir($lockFileName, json_encode([
......@@ -676,7 +670,6 @@ class DataHandlerHook
$t3ver_state = [];
$t3ver_state['swapVersion'] = $swapVersion['t3ver_state'];
// Modify offline version to become online:
$tmp_wsid = $swapVersion['t3ver_wsid'];
// Set pid for ONLINE
$swapVersion['pid'] = (int)$curVersion['pid'];
// We clear this because t3ver_oid only make sense for offline versions
......@@ -688,17 +681,8 @@ class DataHandlerHook
// current workspace ID so the record is not deselected
// in the interface by BackendUtility::versioningPlaceholderClause()
$swapVersion['t3ver_wsid'] = 0;
if ($swapIntoWS) {
if ($t3ver_state['swapVersion'] > 0) {
$swapVersion['t3ver_wsid'] = $dataHandler->BE_USER->workspace;
} else {
$swapVersion['t3ver_wsid'] = (int)$curVersion['t3ver_wsid'];
}
}
$swapVersion['t3ver_stage'] = 0;
if (!$swapIntoWS) {
$swapVersion['t3ver_state'] = (string)new VersionState(VersionState::DEFAULT_STATE);
}
$swapVersion['t3ver_state'] = (string)new VersionState(VersionState::DEFAULT_STATE);
// Moving element.
if (BackendUtility::isTableWorkspaceEnabled($table)) {
// && $t3ver_state['swapVersion']==4 // Maybe we don't need this?
......@@ -728,12 +712,10 @@ class DataHandlerHook
unset($curVersion['uid']);
// Mark curVersion to contain the oid
$curVersion['t3ver_oid'] = (int)$id;
$curVersion['t3ver_wsid'] = $swapIntoWS ? (int)$tmp_wsid : 0;
$curVersion['t3ver_wsid'] = 0;
// Increment lifecycle counter
$curVersion['t3ver_stage'] = 0;
if (!$swapIntoWS) {
$curVersion['t3ver_state'] = (string)new VersionState(VersionState::DEFAULT_STATE);
}
$curVersion['t3ver_state'] = (string)new VersionState(VersionState::DEFAULT_STATE);
// Registering and swapping MM relations in current and swap records:
$dataHandler->version_remapMMForVersionSwap($table, $id, $swapWith);
// Generating proper history data to prepare logging
......@@ -800,29 +782,17 @@ class DataHandlerHook
// If a moving operation took place...:
if ($movePlhID) {
// Remove, if normal publishing:
if (!$swapIntoWS) {
// For delete + completely delete!
$dataHandler->deleteEl($table, $movePlhID, true, true);
} else {
// Otherwise update the movePlaceholder:
GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($table)
->update(
$table,
$movePlh,
['uid' => (int)$movePlhID]
);
$dataHandler->addRemapStackRefIndex($table, $movePlhID);
}
// For delete + completely delete!
$dataHandler->deleteEl($table, $movePlhID, true, true);
}
// Checking for delete:
// Delete only if new/deleted placeholders are there.
if (!$swapIntoWS && ((int)$t3ver_state['swapVersion'] === VersionState::NEW_PLACEHOLDER || (int)$t3ver_state['swapVersion'] === VersionState::DELETE_PLACEHOLDER)) {
if (((int)$t3ver_state['swapVersion'] === VersionState::NEW_PLACEHOLDER || (int)$t3ver_state['swapVersion'] === VersionState::DELETE_PLACEHOLDER)) {
// Force delete
$dataHandler->deleteEl($table, $id, true);
}
if ($dataHandler->enableLogging) {
$dataHandler->log($table, $id, SystemLogGenericAction::UNDEFINED, 0, SystemLogErrorClassification::MESSAGE, ($swapIntoWS ? 'Swapping' : 'Publishing') . ' successful for table "' . $table . '" uid ' . $id . '=>' . $swapWith, -1, [], $dataHandler->eventPid($table, $id, $swapVersion['pid']));
$dataHandler->log($table, $id, SystemLogGenericAction::UNDEFINED, 0, SystemLogErrorClassification::MESSAGE, 'Publishing successful for table "' . $table . '" uid ' . $id . '=>' . $swapWith, -1, [], $dataHandler->eventPid($table, $id, $swapVersion['pid']));
}
// Update reference index of the live record:
......@@ -863,20 +833,18 @@ class DataHandlerHook
// Clear cache:
$dataHandler->registerRecordIdForPageCacheClearing($table, $id);
// If not swapped, delete the record from the database
if (!$swapIntoWS) {
if ($table === 'pages') {
// Note on fifth argument false: At this point both $curVersion and $swapVersion page records are
// identical in DB. deleteEl() would now usually find all records assigned to our obsolete
// page which at the same time belong to our current version page, and would delete them.
// To suppress this, false tells deleteEl() to only delete the obsolete page but not its assigned records.
$dataHandler->deleteEl($table, $swapWith, true, true, false);
} else {
$dataHandler->deleteEl($table, $swapWith, true, true);
}
// If published, delete the record from the database
if ($table === 'pages') {
// Note on fifth argument false: At this point both $curVersion and $swapVersion page records are
// identical in DB. deleteEl() would now usually find all records assigned to our obsolete
// page which at the same time belong to our current version page, and would delete them.
// To suppress this, false tells deleteEl() to only delete the obsolete page but not its assigned records.
$dataHandler->deleteEl($table, $swapWith, true, true, false);
} else {
$dataHandler->deleteEl($table, $swapWith, true, true);
}
//Update reference index for live workspace too:
// Update reference index for live workspace too:
/** @var \TYPO3\CMS\Core\Database\ReferenceIndex $refIndexObj */
$refIndexObj = GeneralUtility::makeInstance(ReferenceIndex::class);
$refIndexObj->setWorkspaceId(0);
......
......@@ -136,7 +136,7 @@ class GridDataService implements LoggerAwareInterface
$backendUser = $this->getBackendUser();
$workspaceAccess = $backendUser->checkWorkspace($backendUser->workspace);
$swapStage = $workspaceAccess['publish_access'] & 1 ? StagesService::STAGE_PUBLISH_ID : 0;
$swapAccess = $backendUser->workspacePublishAccess($backendUser->workspace) && $backendUser->workspaceSwapAccess();
$swapAccess = $backendUser->workspacePublishAccess($backendUser->workspace);
$this->initializeWorkspacesCachingFramework();
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
// check for dataArray in cache
......@@ -207,11 +207,11 @@ class GridDataService implements LoggerAwareInterface
$versionArray['allowedAction_nextStage'] = $isRecordTypeAllowedToModify && $stagesObj->isNextStageAllowedForUser($versionRecord['t3ver_stage']);
$versionArray['allowedAction_prevStage'] = $isRecordTypeAllowedToModify && $stagesObj->isPrevStageAllowedForUser($versionRecord['t3ver_stage']);
if ($swapAccess && $swapStage != 0 && $versionRecord['t3ver_stage'] == $swapStage) {
$versionArray['allowedAction_swap'] = $isRecordTypeAllowedToModify && $stagesObj->isNextStageAllowedForUser($swapStage);