* ``` * * or: * * ```html * {record -> f:render.record()} * ``` * * @see https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-render-record */ final class RecordViewHelper extends AbstractViewHelper { /** * @var bool use content as-is */ protected $escapeOutput = false; public function __construct( private readonly EventDispatcherInterface $eventDispatcher, private readonly TimeTracker $timeTracker, ) {} public function initializeArguments(): void { parent::initializeArguments(); $this->registerArgument('record', RecordInterface::class, 'The record to be rendered'); } public function getContentArgumentName(): string { return 'record'; } public function render(): string { $record = $this->renderChildren(); if (!$record instanceof RecordInterface) { throw new InvalidArgumentValueException('The "record" argument must be an instance of ' . RecordInterface::class, 1770215699); } $request = $this->getRequest(); $result = $this->renderRecord($record, $request); $event = $this->eventDispatcher->dispatch( new ModifyRenderedRecordEvent( renderedRecord: $result, record: $record, request: $request, ), ); return $event->getRenderedRecord(); } private function renderRecord(RecordInterface $record, ServerRequestInterface $request): string { $table = $record->getMainType(); $data = $record->getRawRecord()?->toArray(true) ?? $record->toArray(); $contentObjectRenderer = GeneralUtility::makeInstance(ContentObjectRenderer::class); $contentObjectRenderer->setRequest($request); $parent = $request->getAttribute('currentContentObject'); if ($parent instanceof ContentObjectRenderer) { $contentObjectRenderer->setParent($parent->data, $parent->currentRecord); } $contentObjectRenderer->start($data, $table); $frontendTypoScript = $request->getAttribute('frontend.typoscript'); if (!$frontendTypoScript instanceof FrontendTypoScript || !$frontendTypoScript->hasSetup()) { throw new \RuntimeException( 'Full TypoScript setup is not available in the current request. The "f:render.record" ViewHelper' . ' can only be used in Frontend rendering context.', 1781223613 ); } $setup = $frontendTypoScript->getSetupArray(); if (!isset($setup[$table])) { throw new InvalidArgumentValueException( 'No Content Object definition found at TypoScript object path "' . $table . '"', 1769184455 ); } $timeTracker = $this->timeTracker; if ($timeTracker->LR) { $timeTracker->push('/f:render.record/', '<' . $table); } $timeTracker->incStackPointer(); $content = $contentObjectRenderer->cObjGetSingle($setup[$table], $setup[$table . '.'] ?? [], $table); $timeTracker->decStackPointer(); if ($timeTracker->LR) { $timeTracker->pull($content); } return $content; } private function getRequest(): ServerRequestInterface { if (!$this->renderingContext->hasAttribute(ServerRequestInterface::class)) { throw new \RuntimeException('Required request not found in RenderingContext', 1769508877); } return $this->renderingContext->getAttribute(ServerRequestInterface::class); } }