Skip to content

Commit

Permalink
[!!!][TASK] Do not create new version placeholders in workspaces anymore
Browse files Browse the repository at this point in the history
Creating a new record in a workspace adds two database rows.

One that is the "placeholder", which - since v10.4 - contains
the same metadata as the other record:

* t3ver_wsid = workspaceID
* t3ver_oid = 0 (simulating behavior of an "online pendant record")
* t3ver_state = 1

And the "versionized" record, identified by:

* t3ver_wsid = workspaceID
* t3ver_oid = uid of the new placeholder record
* t3ver_state = -1

As of TYPO3 v10, the first record is not needed anymore,
the versioned record can be queried directly, however, since
the relations (except MM) point to the placeholder record,
this one is kept.

As result, only one record is created from now on:

* t3ver_wsid = workspaceID
* t3ver_oid = 0 (no online counterpart)
* t3ver_state = 1

On reading, the record is queried directly (no overlay needed anymore!)
with the existing Database Doctrine Restrictions. On publishing, the
record just gets the state/stage/wsid set and is "live".

This brings fundamental benefits:

* No overlays needed when querying
* Fewer database records (placeholders are not helpful)
* Conceptual problems with placeholder and shadowed fields are removed

Resolves: #92791
Releases: master
Change-Id: I0288cc63fe72d8442d586f309bd4054ac44e829b
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65587
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Oliver Bartsch <bo@cedev.de>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Bartsch <bo@cedev.de>
Reviewed-by: Benni Mack <benni@typo3.org>
  • Loading branch information
bmack committed Nov 12, 2020
1 parent 1e85f09 commit 74899ec
Show file tree
Hide file tree
Showing 223 changed files with 2,099 additions and 1,926 deletions.
Expand Up @@ -56,6 +56,7 @@
use TYPO3\CMS\Core\Utility\HttpUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
use TYPO3\CMS\Core\Versioning\VersionState;

/**
* Main backend controller almost always used if some database record is edited in the backend.
Expand Down Expand Up @@ -2341,7 +2342,7 @@ protected function getRecordForEdit(string $table, int $theUid)
// Check for versioning support of the table:
if ($tableSupportsVersioning) {
// If the record is already a version of "something" pass it by.
if ($reqRecord['t3ver_oid'] > 0) {
if ($reqRecord['t3ver_oid'] > 0 || (int)$reqRecord['t3ver_state'] === VersionState::NEW_PLACEHOLDER) {
// (If it turns out not to be a version of the current workspace there will be trouble, but
// that is handled inside DataHandler then and in the interface it would clearly be an error of
// links if the user accesses such a scenario)
Expand Down
Expand Up @@ -36,6 +36,7 @@
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\RootlineUtility;
use TYPO3\CMS\Core\Versioning\VersionState;
use TYPO3\CMS\Workspaces\Service\WorkspaceService;

/**
Expand Down Expand Up @@ -584,7 +585,9 @@ protected function resolvePageCssClassNames(array $page): string
}
$workspaceId = (int)$this->getBackendUser()->workspace;
if ($workspaceId > 0 && ExtensionManagementUtility::isLoaded('workspaces')) {
if ($page['t3ver_oid'] > 0 && (int)$page['t3ver_wsid'] === $workspaceId) {
if ((int)$page['t3ver_wsid'] === $workspaceId
&& ((int)$page['t3ver_oid'] > 0 || (int)$page['t3ver_state'] === VersionState::NEW_PLACEHOLDER)
) {
$classes[] = 'ver-element';
$classes[] = 'ver-versions';
} elseif (
Expand Down
Expand Up @@ -480,7 +480,7 @@ public function fetchFilteredTree(string $searchFilter, array $allowedMountPoint
$expressionBuilder = $queryBuilder->expr();

if ($this->currentWorkspace === 0) {
// Only include ws_id=0
// Only include records from live workspace
$workspaceIdExpression = $expressionBuilder->eq('t3ver_wsid', 0);
} else {
// Include live records PLUS records from the given workspace
Expand Down
48 changes: 31 additions & 17 deletions typo3/sysext/backend/Classes/Utility/BackendUtility.php
Expand Up @@ -1189,16 +1189,13 @@ public static function titleAttribForPages($row, $perms_clause = '', $includeAtt
return $includeAttrib ? 'title="' . $out . '"' : $out;
}
switch (VersionState::cast($row['t3ver_state'])) {
case new VersionState(VersionState::NEW_PLACEHOLDER):
$parts[] = 'PLH WSID#' . $row['t3ver_wsid'];
break;
case new VersionState(VersionState::DELETE_PLACEHOLDER):
$parts[] = 'Deleted element!';
break;
case new VersionState(VersionState::MOVE_POINTER):
$parts[] = 'NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
break;
case new VersionState(VersionState::NEW_PLACEHOLDER_VERSION):
case new VersionState(VersionState::NEW_PLACEHOLDER):
$parts[] = 'New element!';
break;
}
Expand Down Expand Up @@ -1300,16 +1297,13 @@ public static function getRecordIconAltText($row, $table = 'pages')
$out .= 'id=' . $row['uid'];
if (static::isTableWorkspaceEnabled($table)) {
switch (VersionState::cast($row['t3ver_state'])) {
case new VersionState(VersionState::NEW_PLACEHOLDER):
$out .= ' - PLH WSID#' . $row['t3ver_wsid'];
break;
case new VersionState(VersionState::DELETE_PLACEHOLDER):
$out .= ' - Deleted element!';
break;
case new VersionState(VersionState::MOVE_POINTER):
$out .= ' - NEW LOCATION (Move-to Pointer) WSID#' . $row['t3ver_wsid'];
break;
case new VersionState(VersionState::NEW_PLACEHOLDER_VERSION):
case new VersionState(VersionState::NEW_PLACEHOLDER):
$out .= ' - New element!';
break;
}
Expand Down Expand Up @@ -3505,8 +3499,10 @@ public static function workspaceOL($table, &$row, $wsid = -99, $unsetMovePointer
$wsAlt['_ORIG_pid'] = $row['pid'];
}
// Swap UID
$wsAlt['_ORIG_uid'] = $wsAlt['uid'];
$wsAlt['uid'] = $row['uid'];
if (!$versionState->equals(VersionState::NEW_PLACEHOLDER)) {
$wsAlt['_ORIG_uid'] = $wsAlt['uid'];
$wsAlt['uid'] = $row['uid'];
}
// Backend css class:
$wsAlt['_CSSCLASS'] = 'ver-element';
// Changing input record to the workspace version alternative:
Expand Down Expand Up @@ -3540,13 +3536,26 @@ public static function getWorkspaceVersionOfRecord($workspace, $table, $uid, $fi
$row = $queryBuilder
->from($table)
->where(
$queryBuilder->expr()->eq(
't3ver_oid',
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
),
$queryBuilder->expr()->eq(
't3ver_wsid',
$queryBuilder->createNamedParameter($workspace, \PDO::PARAM_INT)
),
$queryBuilder->expr()->orX(
// t3ver_state=1 does not contain a t3ver_oid, and returns itself
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq(
'uid',
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
),
$queryBuilder->expr()->eq(
't3ver_state',
$queryBuilder->createNamedParameter(VersionState::NEW_PLACEHOLDER, \PDO::PARAM_INT)
)
),
$queryBuilder->expr()->eq(
't3ver_oid',
$queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
)
)
)
->execute()
Expand Down Expand Up @@ -3590,9 +3599,14 @@ public static function getLiveVersionIdOfRecord($table, $uid)
}
$liveVersionId = null;
if (self::isTableWorkspaceEnabled($table)) {
$currentRecord = self::getRecord($table, $uid, 'pid,t3ver_oid');
if (is_array($currentRecord) && (int)$currentRecord['t3ver_oid'] > 0) {
$liveVersionId = $currentRecord['t3ver_oid'];
$currentRecord = self::getRecord($table, $uid, 'pid,t3ver_oid,t3ver_state');
if (is_array($currentRecord)) {
if ((int)$currentRecord['t3ver_oid'] > 0) {
$liveVersionId = $currentRecord['t3ver_oid'];
} elseif ((int)($currentRecord['t3ver_state']) === VersionState::NEW_PLACEHOLDER) {
// New versions do not have a live counterpart
$liveVersionId = (int)$uid;
}
}
}
return $liveVersionId;
Expand Down
Expand Up @@ -60,7 +60,7 @@ public function __construct(PageLayoutContext $context, GridColumn $column, arra

public function isVersioned(): bool
{
return $this->record['_ORIG_uid'] > 0;
return $this->record['_ORIG_uid'] > 0 || (int)$this->record['t3ver_state'] !== 0;
}

public function getPreview(): string
Expand Down
Expand Up @@ -46,6 +46,7 @@
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\HttpUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Core\Versioning\VersionState;
use TYPO3\CMS\Install\Service\SessionService;

/**
Expand Down Expand Up @@ -928,13 +929,18 @@ public function workspaceCannotEditRecord($table, $recData)
$recData = BackendUtility::getRecord(
$table,
$recData,
'pid' . ($tableSupportsVersioning ? ',t3ver_oid,t3ver_wsid,t3ver_stage' : '')
'pid' . ($tableSupportsVersioning ? ',t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage' : '')
);
}
if (is_array($recData)) {
// We are testing a "version" (identified by having a t3ver_oid): it can be edited provided
// that workspace matches and versioning is enabled for the table.
if ($tableSupportsVersioning && (int)($recData['t3ver_oid'] ?? 0) > 0) {
$versionState = new VersionState($recData['t3ver_state'] ?? 0);
if ($tableSupportsVersioning
&& (
$versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)(($recData['t3ver_oid'] ?? 0) > 0)
)
) {
if ((int)$recData['t3ver_wsid'] !== $this->workspace) {
// So does workspace match?
return 'Workspace ID of record didn\'t match current workspace';
Expand Down Expand Up @@ -970,10 +976,11 @@ public function workspaceCannotEditOfflineVersion($table, $recData)
return 'Table does not support versioning.';
}
if (!is_array($recData)) {
$recData = BackendUtility::getRecord($table, $recData, 'uid,pid,t3ver_oid,t3ver_wsid,t3ver_stage');
$recData = BackendUtility::getRecord($table, $recData, 'uid,pid,t3ver_oid,t3ver_wsid,t3ver_state,t3ver_stage');
}
if (is_array($recData)) {
if ((int)$recData['t3ver_oid'] > 0) {
$versionState = new VersionState($recData['t3ver_state']);
if ($versionState->equals(VersionState::NEW_PLACEHOLDER) || (int)$recData['t3ver_oid'] > 0) {
return $this->workspaceCannotEditRecord($table, $recData);
}
return 'Not an offline version';
Expand Down

0 comments on commit 74899ec

Please sign in to comment.