Breaking: #92434 - Use Record API in Page Module Preview Rendering 

See forge#92434

Description 

The Page Module preview rendering has been refactored to use the Record API internally instead of accessing raw database arrays. This affects both custom preview renderers that extend StandardContentPreviewRenderer and Fluid-based preview templates.

The method signature has changed for \TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer :

  • StandardContentPreviewRenderer->linkEditContent() now expects a RecordInterface object as the second $record parameter instead of an array

The \TYPO3\CMS\Backend\View\Event\PageContentPreviewRenderingEvent has also been updated:

  • PageContentPreviewRenderingEvent->getRecord() now returns a RecordInterface object instead of an array
  • PageContentPreviewRenderingEvent->setRecord() now expects a RecordInterface object instead of an array

Additionally, the @internal class \TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem has been updated to work with Record objects:

  • GridColumnItem() requires a RecordInterface object as the third $record parameter instead of an array
  • GridColumnItem->getRecord() now returns a RecordInterface object instead of an array
  • GridColumnItem->setRecord() now expects a RecordInterface object instead of an array
  • A new method GridColumnItem->getRow() has been added to access the raw database array if needed

For Fluid-based content element previews, the template variables have changed.in Previously, all record fields were passed as individual variables to the Fluid template. Now, only a single {record} variable is passed, which is a RecordInterface object providing access to all record data through the Record API.

Using the {pi_flexform_transformed} in Fluid-based content element previews does no longer work. The resolved flex form can be directly accessed on the RecordInterface object, e.g. via {record.pi_flexform}. The value is a FlexFormFieldValues object. This object properly groups the fields by their sheets.

Impact 

Extensions that extend StandardContentPreviewRenderer and override the linkEditContent() method will need to update their method signature.

Extensions that access GridColumnItem->getRecord() expecting an array will need to update their code to work with RecordInterface objects.

Extensions using event listeners for PageContentPreviewRenderingEvent that access the record via getRecord() expecting an array will need to update their code to work with RecordInterface objects.

Custom Fluid templates for content element preview rendering must be updated to use the {record} variable instead of accessing individual field variables.

Affected Installations 

All installations with extensions that:

  • Extend StandardContentPreviewRenderer and call or override the linkEditContent() method
  • Instantiate GridColumnItem or call GridColumnItem->getRecord() / GridColumnItem->setRecord()
  • Event listeners for PageContentPreviewRenderingEvent
  • Custom Fluid templates for content element preview rendering via PageTSconfig mod.web_layout.tt_content.preview.[recordType]

Migration 

For custom preview renderers extending StandardContentPreviewRenderer:

Update the method signature of linkEditContent() to accept a RecordInterface object:

Before (TYPO3 v13 and lower)
protected function linkEditContent(string $linkText, array $row, string $table = 'tt_content'): string
{
    $uid = (int)$row['uid'];
    $pid = (int)$row['pid'];
    // ...
}
Copied!
After (TYPO3 v14+)
protected function linkEditContent(string $linkText, RecordInterface $record): string
{
    $uid = $record->getUid();
    $pid = $record->getPid();
    $table = $record->getMainType();
    // ...
}
Copied!

For code working with GridColumnItem:

Before (TYPO3 v13 and lower)
$row = $columnItem->getRecord();
$uid = (int)$row['uid'];
$title = $row['header'];
Copied!
After (TYPO3 v14+)
$record = $columnItem->getRecord();
$uid = $record->getUid();
$title = $record->has('header') ? $record->get('header') : '';

// Or if raw array access is needed:
$row = $columnItem->getRow();
$uid = (int)$row['uid'];
Copied!

For custom Fluid templates used for content element preview rendering:

Before (TYPO3 v13 and lower)
<h2>{header}</h2>
<p>{bodytext}</p>
<f:if condition="{image}">
    <p>Image UID: {image}</p>
</f:if>
Copied!
After (TYPO3 v14+)
<h2>{record.header}</h2>
<p>{record.bodytext}</p>
<f:if condition="{record.image}">
    <p>Image UID: {record.image.uid}</p>
</f:if>
Copied!

For flex form value rendering, there are two options:

Before (TYPO3 v13 and lower)
<h2>{header}</h2>
<p>{bodytext}</p>
<small>{pi_flexform_transformed.settings.welcome_header}</small>
<f:if condition="{image}">
    <p>Image UID: {image}</p>
</f:if>
Copied!
After (TYPO3 v14+)
<f:variable name="path" value="s_messages/settings" />
<small>{record.pi_flexform.{path}.welcome_header}</small>

// or

<small>{record.pi_flexform.sheets.s_messages.settings.welcome_header}</small>
Copied!