Products: categories and sub-categories become clickable pages
The 2026-11-02 menu build created the 3 categories and 9 sub-categories as sysfolders (labels); every level must be a clickable page. - build-product-overviews: six sub-categories adopt the 2026-10 category pages (Joe's workbooks; content, slug and SEO kept, sitemap name as nav_title), the remaining folders become pages with generated content, Capture & Graphics gets the main column of Graphics & Multi-Display and Video Capture copied in. Pages move/convert by direct UPDATE (the redirects slug hook would rewrite the flat child slugs); three 2026-10 pages leave the menus but stay reachable. Warns about a sys_redirect on a target slug. - ProvideProductCatalog: categories[].link and groups[].link (additive), menu title = nav_title when set, only filled groups/categories count. The menu search reads both levels as pages too. - build-why-vitec-bands: band at the top of the main column; on pages with an existing "Why VITEC?" section the context's icons go onto the cards whose title matches the icon theme (16 icons on 4 pages). - No browser cache headers on the page JSON: headless enables sendCacheHeaders and TYPO3 14 caches pages for a year by default, so every /_json/ response carried max-age=~31536000. - Spec v1.32. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
73e4298b75
commit
bd7a145afa
6 files changed
+627
-79
No files matched your search
@@ -77,8 +77,10 @@ final class ProductMenuSearchJsonRenderer
|
||||
}
|
||||
|
||||
/**
|
||||
* The overview pages of the products menu tree (/products > folder >
|
||||
* folder > page, see ProvideProductCatalog) with their menu path.
|
||||
* The overview pages of the products menu tree (/products > category >
|
||||
* sub-category > page, see ProvideProductCatalog) with their menu path.
|
||||
* Category and sub-category are pages since 2026-11-05 (folders before -
|
||||
* both are read).
|
||||
*
|
||||
* @return array<int,array{uid:int,title:string,link:string,path:string[]}> page uid => overview
|
||||
*/
|
||||
@@ -96,7 +98,7 @@ final class ProductMenuSearchJsonRenderer
|
||||
return [];
|
||||
}
|
||||
$queryBuilder = $pool->getQueryBuilderForTable('pages');
|
||||
return $queryBuilder->select('uid', 'pid', 'title', 'slug')->from('pages')
|
||||
$rows = $queryBuilder->select('uid', 'pid', 'title', 'nav_title', 'slug')->from('pages')
|
||||
->where(
|
||||
$queryBuilder->expr()->in('pid', $queryBuilder->createNamedParameter($parents, ArrayParameterType::INTEGER)),
|
||||
$queryBuilder->expr()->in('doktype', $queryBuilder->createNamedParameter($doktypes, ArrayParameterType::INTEGER)),
|
||||
@@ -104,9 +106,16 @@ final class ProductMenuSearchJsonRenderer
|
||||
)
|
||||
->orderBy('sorting')
|
||||
->executeQuery()->fetchAllAssociative();
|
||||
// menu label = nav_title when set (same rule as ProvideProductCatalog)
|
||||
foreach ($rows as &$row) {
|
||||
if (trim((string)($row['nav_title'] ?? '')) !== '') {
|
||||
$row['title'] = $row['nav_title'];
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
};
|
||||
$categories = array_column($level([$root], [254]), null, 'uid');
|
||||
$groups = array_column($level(array_keys($categories), [254]), null, 'uid');
|
||||
$categories = array_column($level([$root], [1, 254]), null, 'uid');
|
||||
$groups = array_column($level(array_keys($categories), [1, 254]), null, 'uid');
|
||||
$overviews = [];
|
||||
foreach ($level(array_keys($groups), [1]) as $page) {
|
||||
$group = $groups[(int)$page['pid']];
|
||||
|
||||
Reference in new issue
Block a user