`, legacy content as `` tags, images with * relative paths. Fluid resolves those through `parseFunc` when it renders; a * headless UserFunc renderer that hands the raw column straight to JSON does * not, and the frontend receives dead links. * * The two upstream packages already close this gap for the output they own: * `friendsoftypo3/headless` applies `parseFunc =< lib.parseFunc_RTE` to the core * text elements via TypoScript, and `nb-headless-content-blocks` calls * `parseFunc($value, null, '< lib.parseFunc_RTE')` for every Content Block field * whose TCA has `enableRichtext`. This class closes it for the VITEC UserFunc * renderers, using exactly the same call. * * Static by design: the conversion is stateless, and the call sites are payload * array literals where a `GeneralUtility::makeInstance(...)->` prefix would add * only noise. Same rationale as `CropVariants::firstImage()` and * `FormDefinitions::get()`. * * Fail-soft per architecture spec clause 9.5: when parsing is impossible — most * notably outside a frontend request, where no TypoScript setup exists — the raw * value is returned. Content is never lost; at worst it stays unresolved. */ final class RteResolver { /** * @param mixed $value raw column value; null and non-strings are tolerated */ public static function html(mixed $value): string { $raw = (string)($value ?? ''); if (trim($raw) === '') { return ''; } try { $parsed = GeneralUtility::makeInstance(ContentObjectRenderer::class) ->parseFunc($raw, null, '< lib.parseFunc_RTE'); return $parsed !== '' ? $parsed : $raw; } catch (\Throwable $e) { return $raw; } } }