Bug #93484
closedTYPO3 Workspace, Preview module raising exception for versioned plugin records
100%
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 <info@typoworx.com>
*/
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