diff --git a/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php b/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php index ff1a0de..0f20425 100755 --- a/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php +++ b/packages/vitec/Classes/UserFunc/ProductListJsonRenderer.php @@ -207,9 +207,13 @@ class ProductListJsonRenderer // Success stories the editor attached to these categories // (sys_category, Options tab). They ride along with the list // so the front end can hide them with the same category - // filter it applies to the products. + // filter it applies to the products. An all-products element + // aggregates over the WHOLE product category tree (change + // 2026-09-16 on front-end request - it used to deliver the + // empty envelope), so forCategories keeps driving the + // ?cat=/?subcat= filter exactly like on per-category lists. 'successStories' => $this->successStoriesFor( - $allProducts ? [] : $categoryUids, + ($allProducts || $categoryUids === []) ? $this->allProductCategoryUids() : $categoryUids, (int)($settings['storysinglepid'] ?? 0) ), ]; @@ -375,6 +379,34 @@ class ProductListJsonRenderer * @param int[] $categoryUids * @return int[] */ + /** + * The whole product category tree - the root's children plus all + * descendants in depth-first backend order. Story source for elements + * that render all products. Root detection mirrors + * ProductFinderJsonRenderer: the root-level sys_category named 'Product'. + * + * @return int[] + */ + private function allProductCategoryUids(): array + { + $queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class) + ->getQueryBuilderForTable('sys_category'); + $rootUid = (int)($queryBuilder->select('uid')->from('sys_category') + ->where( + $queryBuilder->expr()->eq('parent', 0), + $queryBuilder->expr()->eq('deleted', 0), + $queryBuilder->expr()->eq('title', $queryBuilder->createNamedParameter('Product', ParameterType::STRING)) + ) + ->setMaxResults(1) + ->executeQuery()->fetchOne() ?: 0); + if ($rootUid <= 0) { + return []; + } + + // Drop the root itself - stories hang on the categories below it. + return array_values(array_diff($this->expandWithDescendants([$rootUid]), [$rootUid])); + } + private function expandWithDescendants(array $categoryUids): array { $queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)