Real JSON null for empty product feature; SSR warm-cache button and CLI

Ticket 0068-FE: ProductFeatureJsonRenderer returned json_encode(null), which headless passes on as the STRING null (it only decodes object/array-looking strings) and crashed the front end. It now returns an empty string and the TypoScript field sets ifEmptyReturnNull = 1, giving a real JSON null. No other renderer used the pattern. Ticket 0066-FE: SsrPurgeService::warm() posts to the node /__warm endpoint (derived from SSR_PURGE_ENDPOINT, same secret), exposed as a Warm cache button with confirmation in the VITEC SSR module, a Cache warming progress row fed by /__health, and the CLI vitec:ssr-warm [paths]. Warm runs are deliberately not written to the purge log. Verified: two-path run 2/2 done, affected page delivers productfeature null.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
orascheandClaude Fable 5.2 committed 2026-11-10 10:59:24 +01:00
1 parent cb53ff67ee
commit 8f8ae039d4
7 files changed
+176 -3

No files matched your search

@@ -21,6 +21,12 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
*
* Extends ProductListJsonRenderer purely to reuse its serializeProduct()
* and image handling - same filters, same shape, one source of truth.
*
* "No product" returns an EMPTY STRING, never json_encode(null): headless
* only decodes strings that look like objects/arrays, so the text "null"
* went out as the string "null" and crashed the front end (ticket
* 0068-FE). The TypoScript sets ifEmptyReturnNull = 1 on this field,
* which turns the empty string into a real JSON null.
*/
final class ProductFeatureJsonRenderer extends ProductListJsonRenderer
{
@@ -33,7 +39,7 @@ final class ProductFeatureJsonRenderer extends ProductListJsonRenderer
->convertFlexFormContentToArray((string)($row['pi_flexform'] ?? ''));
$productUid = (int)($flexFormData['settings']['product'] ?? 0);
if ($productUid <= 0) {
return (string)json_encode(null);
return '';
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
@@ -47,12 +53,12 @@ final class ProductFeatureJsonRenderer extends ProductListJsonRenderer
)
->executeQuery()->fetchAssociative();
if (!$product) {
return (string)json_encode(null);
return '';
}
return (string)json_encode($this->serializeProduct($product), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
} catch (\Throwable) {
return (string)json_encode(null);
return '';
}
}
}