Commit 01c6cdc1 authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Keep pid for versioned records

DataHandler does not set "-1" for versioned records in workspaces
anymore, thus making it a lot easier to find the real PID for a versioned
record without always having to fetch the live version for it.

This is ground-breaking, as this opens the door for a lot of improvements
when accessing versions via overlays.

An upgrade wizard will migrate all pid=-1 records to their equivalent
pids, and discard all already published / archived versions.

Resolves: #89555
Releases: master
Change-Id: I31c32451827c1f94764bb0ba22ad8207c8b3d4fd
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61699

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Tested-by: Manuel Selbach's avatarManuel Selbach <manuel_selbach@yahoo.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Oliver Hader's avatarOliver Hader <oliver.hader@typo3.org>
Reviewed-by: Manuel Selbach's avatarManuel Selbach <manuel_selbach@yahoo.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent ded3c9f6
......@@ -27,8 +27,8 @@ use TYPO3\CMS\Backend\View\PageLayoutView;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Configuration\Features;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Imaging\Icon;
......@@ -229,7 +229,7 @@ class PageLayoutController
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$statement = $queryBuilder->select('uid', $GLOBALS['TCA']['pages']['ctrl']['languageField'])
->from('pages')
->where(
......@@ -496,7 +496,7 @@ class PageLayoutController
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$localizedPage = $queryBuilder
->select('*')
->from('pages')
......@@ -794,7 +794,7 @@ class PageLayoutController
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$overlayRecord = $queryBuilder
->select('uid')
->from('pages')
......@@ -811,6 +811,7 @@ class PageLayoutController
->setMaxResults(1)
->execute()
->fetch();
BackendUtility::workspaceOL('pages', $overlayRecord, (int)$this->getBackendUser()->workspace);
// Edit button
$urlParameters = [
'edit' => [
......@@ -865,7 +866,7 @@ class PageLayoutController
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$queryBuilder
->count('uid')
......
......@@ -31,8 +31,8 @@ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Configuration\SiteConfiguration;
use TYPO3\CMS\Core\Core\Environment;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Domain\Repository\PageRepository;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\HtmlResponse;
......@@ -633,7 +633,7 @@ class SiteConfigurationController
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()->removeByType(HiddenRestriction::class);
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, 0, false));
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
$statement = $queryBuilder
->select('*')
->from('pages')
......
......@@ -15,9 +15,10 @@ namespace TYPO3\CMS\Backend\Form\FormDataProvider;
*/
use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
......@@ -51,12 +52,14 @@ class DatabasePageLanguageOverlayRows implements FormDataProviderInterface
*/
protected function getDatabaseRows(int $pid): array
{
$context = GeneralUtility::makeInstance(Context::class);
$workspaceId = $context->getPropertyFromAspect('workspace', 'id');
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$workspaceId));
$rows = $queryBuilder->select('*')
->from('pages')
......
......@@ -19,8 +19,8 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
......@@ -102,7 +102,7 @@ class SuggestWizardDefaultReceiver
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
// if table is versionized, only get the records from the Live Workspace
// the overlay itself of WS-records is done below
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, 0));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
$this->table = $table;
$this->config = $config;
// get a list of all the pages that should be looked on
......
......@@ -19,8 +19,8 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
......@@ -813,7 +813,7 @@ abstract class AbstractTreeView
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->BE_USER->workspace));
$count = $queryBuilder
->count('uid')
->from($this->table)
......@@ -869,7 +869,7 @@ abstract class AbstractTreeView
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->BE_USER->workspace));
$queryBuilder
->select(...$this->fieldArray)
->from($this->table)
......
......@@ -19,10 +19,10 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendLayoutView;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
......@@ -361,7 +361,7 @@ class PagePositionMap
$lines = [];
foreach ($colPosArray as $kk => $vv) {
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
if ($showHidden) {
$queryBuilder->getRestrictions()
->removeByType(HiddenRestriction::class)
......
......@@ -21,8 +21,8 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\PageLayoutView;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
......@@ -198,7 +198,7 @@ class ContentFetcher
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$GLOBALS['BE_USER']->workspace));
$queryBuilder
->select(...$fields)
->from('tt_content');
......
......@@ -20,8 +20,8 @@ use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Site\Entity\NullSite;
......@@ -241,7 +241,7 @@ class DrawingConfiguration
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$localizedPage = $queryBuilder
->select('*')
->from('pages')
......@@ -293,7 +293,7 @@ class DrawingConfiguration
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$queryBuilder->select('uid', $GLOBALS['TCA']['pages']['ctrl']['languageField'])
->from('pages')
->where(
......
......@@ -31,8 +31,8 @@ use TYPO3\CMS\Core\Core\Environment;
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\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Database\ReferenceIndex;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Imaging\Icon;
......@@ -1418,7 +1418,7 @@ class PageLayoutView implements LoggerAwareInterface
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class, null, false));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
$queryBuilder
->select('*')
->from('tt_content')
......@@ -1567,7 +1567,7 @@ class PageLayoutView implements LoggerAwareInterface
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$queryBuilder->select('uid', $GLOBALS['TCA']['pages']['ctrl']['languageField'])
->from('pages')
->where(
......@@ -1883,7 +1883,7 @@ class PageLayoutView implements LoggerAwareInterface
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$queryBuilder
->select(...$fields)
->from($table);
......@@ -1993,7 +1993,7 @@ class PageLayoutView implements LoggerAwareInterface
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace));
$localizedPage = $queryBuilder
->select('*')
->from('pages')
......
......@@ -24,10 +24,10 @@ use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\RootLevelRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
use TYPO3\CMS\Core\Mail\FluidEmail;
use TYPO3\CMS\Core\Mail\Mailer;
......@@ -760,7 +760,7 @@ class BackendUserAuthentication extends AbstractUserAuthentication
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->workspace));
$recordLocalizations = $queryBuilder->select('*')
->from($table)
->where(
......
......@@ -244,16 +244,12 @@ class SlugHelper
$recordId = $state->getSubject()->getIdentifier();
$languageId = $state->getContext()->getLanguageId();
if ($pageId < 0) {
$pageId = $this->resolveLivePageId($recordId);
}
$queryBuilder = $this->createPreparedQueryBuilder();
$this->applySlugConstraint($queryBuilder, $slug);
$this->applyPageIdConstraint($queryBuilder, $pageId);
$this->applyRecordConstraint($queryBuilder, $recordId);
$this->applyLanguageConstraint($queryBuilder, $languageId);
$this->applyWorkspaceConstraint($queryBuilder);
$this->applyWorkspaceConstraint($queryBuilder, $state);
$statement = $queryBuilder->execute();
$records = $this->resolveVersionOverlays(
......@@ -282,15 +278,11 @@ class SlugHelper
}
$pageId = (int)$pageId;
if ($pageId < 0) {
$pageId = $this->resolveLivePageId($recordId);
}
$queryBuilder = $this->createPreparedQueryBuilder();
$this->applySlugConstraint($queryBuilder, $slug);
$this->applyRecordConstraint($queryBuilder, $recordId);
$this->applyLanguageConstraint($queryBuilder, $languageId);
$this->applyWorkspaceConstraint($queryBuilder);
$this->applyWorkspaceConstraint($queryBuilder, $state);
$statement = $queryBuilder->execute();
$records = $this->resolveVersionOverlays(
......@@ -401,6 +393,7 @@ class SlugHelper
$fieldNames = ['uid', 'pid', $this->fieldName];
if ($this->workspaceEnabled) {
$fieldNames[] = 't3ver_state';
$fieldNames[] = 't3ver_oid';
}
$languageFieldName = $GLOBALS['TCA'][$this->tableName]['ctrl']['languageField'] ?? null;
if (is_string($languageFieldName)) {
......@@ -423,8 +416,9 @@ class SlugHelper
/**
* @param QueryBuilder $queryBuilder
* @param RecordState $state
*/
protected function applyWorkspaceConstraint(QueryBuilder $queryBuilder)
protected function applyWorkspaceConstraint(QueryBuilder $queryBuilder, RecordState $state)
{
if (!$this->workspaceEnabled) {
return;
......@@ -433,6 +427,13 @@ class SlugHelper
$queryBuilder->getRestrictions()->add(
GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->workspaceId)
);
// Exclude the online record of a versioned record
if ($state->getVersionLink()) {
$queryBuilder->andWhere(
$queryBuilder->expr()->neq('uid', $state->getVersionLink()->getSubject()->getIdentifier())
);
}
}
/**
......@@ -515,43 +516,6 @@ class SlugHelper
}
}
/**
* @param int $recordId
* @return int
* @throws \RuntimeException
*/
protected function resolveLivePageId($recordId): int
{
if (!MathUtility::canBeInterpretedAsInteger($recordId)) {
throw new \RuntimeException(
sprintf(
'Cannot resolve live page id for non-numeric identifier "%s"',
$recordId
),
1534951024
);
}
$liveVersion = BackendUtility::getLiveVersionOfRecord(
$this->tableName,
$recordId,
'pid'
);
if (empty($liveVersion)) {
throw new \RuntimeException(
sprintf(
'Cannot resolve live page id for record "%s:%d"',
$this->tableName,
$recordId
),
1534951025
);
}
return (int)$liveVersion['pid'];
}
/**
* @param array $records
* @return array
......
......@@ -1279,6 +1279,7 @@ class PageRepository implements LoggerAwareInterface
$constraints[] = $expressionBuilder->eq($table . '.' . $ctrl['delete'], 0);
}
if ($this->hasTableWorkspaceSupport($table)) {
// this should work exactly as WorkspaceRestriction and WorkspaceRestriction should be used instead
if ($this->versioningWorkspaceId === 0) {
// Filter out placeholder records (new/moved/deleted items)
// in case we are NOT in a versioning preview (that means we are online!)
......@@ -1286,7 +1287,8 @@ class PageRepository implements LoggerAwareInterface
$table . '.t3ver_state',
new VersionState(VersionState::DEFAULT_STATE)
);
} elseif ($table !== 'pages') {
$constraints[] = $expressionBuilder->eq($table . '.t3ver_wsid', 0);
} else {
// show only records of live and of the current workspace
// in case we are in a versioning preview
$constraints[] = $expressionBuilder->orX(
......@@ -1297,7 +1299,8 @@ class PageRepository implements LoggerAwareInterface
// Filter out versioned records
if (empty($ignore_array['pid'])) {
$constraints[] = $expressionBuilder->neq($table . '.pid', -1);
// Always filter out versioned records that have an "offline" record
$constraints[] = $expressionBuilder->eq($table . '.t3ver_oid', 0);
}
}
......
.. include:: ../../Includes.txt
==================================================================================
Important: #89555 - Workspace-related database records contain the proper Page ID.
==================================================================================
See :issue:`89555`
Description
===========
Back in 2006, when the workspaces functionality was added to TYPO3 v4.0, Kasper - the original author of TYPO3 - provided an easy way to put workspaces on top while not worrying about existing logic. Every record that wasn't published had the "pid" field set to "-1" - and thus was filtered out from any database query without having to worry about specific implementations.
14 years later, we have Doctrine DBAL and the solution for "enableFields" has been widely been replaced by Database Restrictions, allowing to modify database queries by TYPO3 Core without having to worry about custom queries.
For workspaces however, it is and was very tedious to find the "real pid" for versioned records, and the "pid = -1" scenario is also one of the reasons why workspace overlays are more complex than they need to be.
For this reason, TYPO3 Core now handles versioned records by validating their "t3ver_wsid" (the workspace ID the record is versioned in), "t3ver_state" (the type of the versioned record) and "t3ver_oid" (the live version of a record), and does not need to check for "pid=-1" anymore.
This opens up a more straightforward approach to select and overlay
records and reduce the need for some magic methods in TYPO3 Core,
which still exist.
An Upgrade Wizard transfers all "pid" fields of versioned records,
into the real "pid" fields. TYPO3 Core now only checks for versionized records based on the other fields above.
Please note: This only affects TYPO3 installations with workspaces enabled, and nothing should change for any extension if they use
proper WorkspaceRestriction or Workspace Overlay mechanisms in TYPO3 v10.
.. index:: Database, ext:workspaces
\ No newline at end of file
......@@ -361,10 +361,11 @@ class PageRepositoryTest extends \TYPO3\TestingFramework\Core\Functional\Functio
$connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('pages');
$expectedSQL = sprintf(
' AND ((%s = 0) AND (%s <= 0) AND (%s <> -1) AND (%s = 0) AND (%s <= 1451779200) AND ((%s = 0) OR (%s > 1451779200))) AND (%s <> 255)',
' AND ((%s = 0) AND (%s <= 0) AND (%s = 0) AND (%s = 0) AND (%s = 0) AND (%s <= 1451779200) AND ((%s = 0) OR (%s > 1451779200))) AND (%s <> 255)',
$connection->quoteIdentifier('pages.deleted'),
$connection->quoteIdentifier('pages.t3ver_state'),
$connection->quoteIdentifier('pages.pid'),
$connection->quoteIdentifier('pages.t3ver_wsid'),
$connection->quoteIdentifier('pages.t3ver_oid'),
$connection->quoteIdentifier('pages.hidden'),
$connection->quoteIdentifier('pages.starttime'),
$connection->quoteIdentifier('pages.endtime'),
......@@ -448,8 +449,8 @@ class PageRepositoryTest extends \TYPO3\TestingFramework\Core\Functional\Functio
);
self::assertThat(
$conditions,
self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.pid') . ' <> -1)'),
'Records from page -1'
self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_oid') . ' = 0)'),
'Records with online version'
);
}
......@@ -479,8 +480,8 @@ class PageRepositoryTest extends \TYPO3\TestingFramework\Core\Functional\Functio
);
self::assertThat(
$conditions,
self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.pid') . ' <> -1)'),
'Records from page -1'
self::stringContains(' AND (' . $connection->quoteIdentifier($table . '.t3ver_oid') . ' = 0)'),
'Records from online versions'
);
}
......
......@@ -83,7 +83,7 @@
</pages>
<pages>
<uid>12</uid>
<pid>-1</pid>
<pid>0</pid>
<title>Workspace Root</title>
<deleted>0</deleted>
<t3ver_oid>11</t3ver_oid>
......
......@@ -82,7 +82,7 @@
</pages>
<pages>
<uid>12</uid>
<pid>-1</pid>
<pid>0</pid>
<title>Workspace Root</title>
<deleted>0</deleted>
<t3ver_oid>11</t3ver_oid>
......
......@@ -25,8 +25,8 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\QueryHelper;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Exception;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Imaging\Icon;
......@@ -404,13 +404,13 @@ class ExportController extends ImportExportController
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$orderBy = $GLOBALS['TCA'][$table]['ctrl']['sortby'] ?: $GLOBALS['TCA'][$table]['ctrl']['default_sortby'];
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
$queryBuilder->getRestrictions()->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
if ($this->excludeDisabledRecords === false) {
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
}
$queryBuilder->select('*')
......
......@@ -19,8 +19,8 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Configuration\Loader\PageTsConfigLoader;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
......@@ -253,7 +253,7 @@ class InfoPageTyposcriptConfigController
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class));
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0));
$res = $queryBuilder
->select('uid', 'TSconfig')
......
......@@ -19,8 +19,8 @@ use TYPO3\CMS\Backend\Tree\View\PageTreeView;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\BackendWorkspaceRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
......@@ -388,7 +388,7 @@ class TranslationStatusController
$queryBuilder
->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(BackendWorkspaceRestriction::class))
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace))
->add(GeneralUtility::makeInstance(DeletedRestriction::class));</