Skip to content

Commit

Permalink
[BUGFIX] Correct workspace overlays in DataMapProcessor
Browse files Browse the repository at this point in the history
Scenario:
* Create a live page that has a 'media' resource
* Create a localization of that page
* Go to workspace
* Edit the localized page
* Save
* Save again
-> crash "Array to string conversion" in DataHandler
   isSubmittedValueEqualToStoredValue()

Investigating this, the issue is not in
isSubmittedValueEqualToStoredValue() itself, but
within DataMapProcessor, which fails to apply
a workspace overlay due to #92209: The default
WorkspaceRestriction is not sufficient in this case.

The patch changes DataMapProcessor to apply
workspace overlays in a different way for this
special case.

Resolves: #97989
Related: #92209
Releases: main, 11.5
Change-Id: I176aa2d2e209224b48517b872ea39b1e01f06af7
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/75272
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
  • Loading branch information
lolli42 committed Jul 23, 2022
1 parent d8693af commit dfc8e81
Showing 1 changed file with 33 additions and 11 deletions.
Expand Up @@ -31,6 +31,7 @@
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Core\Utility\StringUtility;
use TYPO3\CMS\Core\Versioning\VersionState;

/**
* This processor analyzes the provided data-map before actually being process
Expand Down Expand Up @@ -871,25 +872,46 @@ protected function fetchTranslationValues(string $tableName, array $fieldNames,
return [];
}

$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
->getQueryBuilderForTable($tableName);
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->backendUser->workspace));
$statement = $queryBuilder
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($tableName);
$queryBuilder->getRestrictions()->removeAll()
// NOT using WorkspaceRestriction here since it's wrong in this case. See ws OR restriction below.
->add(GeneralUtility::makeInstance(DeletedRestriction::class));

$expressions = [
$queryBuilder->expr()->eq('t3ver_wsid', 0),

This comment has been minimized.

Copy link
@phantasie-schmiede

phantasie-schmiede Aug 10, 2022

@lolli42: Due to this line the field t3ver_wsid is required for all tables! According to the documentation and earlier behaviour this field should only be needed if a table supports versioning (https://docs.typo3.org/m/typo3/reference-tca/main/en-us/Ctrl/Properties/VersioningWS.html). Why is this condition outside of the following if-statement?

];
if ($this->backendUser->workspace > 0 && BackendUtility::isTableWorkspaceEnabled($tableName)) {
// If this is a workspace record (t3ver_wsid = be-user-workspace), then fetch this one
// if it is NOT a deleted placeholder (t3ver_state=2), but ok with casual overlay (t3ver_state=0),
// new ws-record (t3ver_state=1), or moved record (t3ver_state=4).
// It *might* be possible to simplify this since it may be the case that ws-deleted records are
// impossible to be incoming here at all? But this query is a safe thing, so we go with it for now.
$expressions[] = $queryBuilder->expr()->and(
$queryBuilder->expr()->eq('t3ver_wsid', $queryBuilder->createNamedParameter($this->backendUser->workspace, \PDO::PARAM_INT)),
$queryBuilder->expr()->in(
't3ver_state',
$queryBuilder->createNamedParameter(
[VersionState::DEFAULT_STATE, VersionState::NEW_PLACEHOLDER, VersionState::MOVE_POINTER],
Connection::PARAM_INT_ARRAY
)
),
);
}
$queryBuilder
->select(...array_values($fieldNames))
->from($tableName)
->where(
$queryBuilder->expr()->in(
'uid',
$queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY)
)
)
->executeQuery();
),
$queryBuilder->expr()->or(...$expressions)
);

$result = $queryBuilder->executeQuery();

$translationValues = [];
while ($record = $statement->fetchAssociative()) {
while ($record = $result->fetchAssociative()) {
$translationValues[$record['uid']] = $record;
}
return $translationValues;
Expand Down

0 comments on commit dfc8e81

Please sign in to comment.