Bug #93484

TYPO3 Workspace, Preview module raising exception for versioned plugin records

Added by Gabriel Kaufmann / Typoworx NewMedia 9 months ago. Updated 4 months ago.

Status:
Closed
Priority:
Should have
Assignee:
-
Category:
Workspaces
Target version:
-
Start date:
2021-02-10
Due date:
% Done:

100%

Estimated time:
TYPO3 Version:
9
PHP Version:
7.2
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

I noticed a very strange error. We had to migrate a TYPO3 instance to TYPO3 v9 which was previously was using TYPO3 Workspaces.

Our customer noticed an Exception trying to use the "Page Preview" Module in a draft workspace on a page which contains a plugin with (workspace ready) plugin records.

The exception aims that the workspace versioning function for some reason tries to access a "uid_local" field which does not exist on the given record! After hours of debugging I noticed that this is caused by $source of type TYPO3\CMS\Extbase\Persistence\Generic\Qom\Join given to TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend::overlayLanguageAndWorkspace. For some reason the original core function is not able to build a valid query and simply returns the original rows (even through there still is some kind of logic which seems to try catch this case).

I was able to create a patch which seems to work fine so far. I'm XClassing around Typo3DbBackend and before calling the parent::overlayLanguageAndWorkspace I'm checking if the given $source is a Join!

If this is the case I'm breaking down the whole thing by re-creating a new $source of type Selector (simple query without join) giving this one to the original function. I think the rest is validly handled by the workspace-versioned model/record itself. So far I was not able to find side-effects of breaking of the Join into a simple "Select" Query for the table without the join (in my case it was for sys-category).

```
namespace Sit\SitConfigGeneric\Core\Persistence\Generic\Storage;

use TYPO3\CMS\Extbase\Persistence\QueryInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
use TYPO3\CMS\Extbase\Persistence\Generic\Qom\Join;
use TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface;
use TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelFactory;

/** * Class Typo3DbBackend * @package TYPOworx\CorePatches\Core * * @author Gabriel Kaufmann <>
*/
class Typo3DbBackend extends \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbBackend {
/** * Performs workspace and language overlay on the given row array. The language and workspace id is automatically * detected (depending on FE or BE context). You can also explicitly set the language/workspace id. * * @param SourceInterface|\TYPO3\CMS\Extbase\Persistence\Generic\Qom\Join $source The source (selector or join) * @param array $rows * @param QueryInterface $query * @param int|null $workspaceUid * @return array * @throws \TYPO3\CMS\Core\Context\Exception\AspectNotFoundException * @throws \Throwable
*/
protected function overlayLanguageAndWorkspace(SourceInterface $source, array $rows, QueryInterface $query, int $workspaceUid = null): array {
try {
/** * For unknwon reason the TYPO3 Core dev's didn't expect * that some join-types would skrew the ::overlayLanguageAndWorkspace, * because it mistakenly uses the right table, but fields that belong to * the Join'ed relation :sic:
*/
if($source instanceof Join) {
/*
$sourceModel = '\\' . ltrim( get_class($source), '\\');

$refactoredSource = $this->objectManager->get(
$sourceModel,
$this->getTableNameFromModel($query->getType()),
$query->getType()
);
*/
$qob = $this->objectManager->get(QueryObjectModelFactory::class);
$refactoredSource = $qob->selector($this->getTableNameFromModel($query->getType()), $query->getType());
}
else {
$refactoredSource = $source;
} {
throw $e;
}
}
$workspaceRows = parent::overlayLanguageAndWorkspace($refactoredSource, $rows, $query, $workspaceUid);
return $workspaceRows;
}
catch (\Throwable $e)
/**
 * @param $model
 * @return string|null
 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception
*/
protected function getTableNameFromModel($model) :? string {
if(is_object($model)) {
$model = get_class($model);
}
$model = '\\' . ltrim($model, '\\');
$dataMapper = $this->objectManager->get(DataMapper::class);
return $dataMapper->getDataMap($model)->getTableName();
}
}
```

I'm not perfectly shure - but I think it makes sense to apply the same patch around ::doLanguageAndWorkspaceOverlay as well.

Please discuss if it makes sense to apply this to the original core-class. I know workspaces in TYPO3 v9 and upwards are still unstable! But may be this will help to "harden" this feature a little bit more.


Files

Auswahl_006.jpg (76 KB) Auswahl_006.jpg Gabriel Kaufmann / Typoworx NewMedia, 2021-02-10 18:18
Typo3DbBackend.php.patch (5.45 KB) Typo3DbBackend.php.patch Gabriel Kaufmann / Typoworx NewMedia, 2021-02-11 10:37

Related issues

Related to TYPO3 Core - Bug #94140: PHP Warning appears when preview in workspace and item of mm relation is disabledNew2021-05-14

Actions

Also available in: Atom PDF