From 0e7f7ebf39a4717aa9df7b86df866798cdeb3a6e Mon Sep 17 00:00:00 2001 From: mrwhy-orig Date: Wed, 18 Oct 2023 14:06:00 +0200 Subject: [PATCH 1/6] Update MenuRepository.php Adding method stub for anchor menu --- Classes/Domain/Repository/MenuRepository.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index 86425c4..837971b 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -42,6 +42,11 @@ public function __construct(Context $context, PageRepository $pageRepository, Ev $this->eventDispatcher = $eventDispatcher; } + public function getAnchorMenu(int $pageId, array $configuration): array + { + $page = $this->getPage($pageId, $configuration); + } + public function getBreadcrumbsMenu(array $originalRootLine, array $configuration): array { $pages = []; From 247cb6aa59f0eac12caa8d7e4b4fec07d215b0a6 Mon Sep 17 00:00:00 2001 From: mrwhy-orig Date: Fri, 27 Oct 2023 22:12:05 +0200 Subject: [PATCH 2/6] Update MenuRepository.php Anchor menu wip --- Classes/Domain/Repository/MenuRepository.php | 22 ++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index 837971b..8937f40 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -27,6 +27,7 @@ class MenuRepository protected Context $context; protected PageRepository $pageRepository; protected EventDispatcherInterface $eventDispatcher; + private readonly ConnectionPool $connectionPool; // Never show or query them. protected $excludedDoktypes = [ @@ -35,16 +36,33 @@ class MenuRepository PageRepository::DOKTYPE_SYSFOLDER, ]; - public function __construct(Context $context, PageRepository $pageRepository, EventDispatcherInterface $eventDispatcher) + public function __construct(Context $context, PageRepository $pageRepository, EventDispatcherInterface $eventDispatcher, ConnectionPool $connectionPool) { $this->context = $context; $this->pageRepository = $pageRepository; $this->eventDispatcher = $eventDispatcher; + $this->connectionPool = $connectionPool; } public function getAnchorMenu(int $pageId, array $configuration): array { - $page = $this->getPage($pageId, $configuration); + //Get the queryBuilder for tt_content + $queryBuilder = $this->connectionPool + ->getQueryBuilderForTable('tt_content'); + + $result = $queryBuilder + ->select("header") + ->from("tt_content") + ->where($queryBuilder->exp()->eq("pid", $queryBuilder->createNamedParameter($pageId))) + ->andWhere($queryBuilder->exp()->neq("delete", 1)) + ->orderBy("sorting") + ->executeQuery(); + + $menu = []; + while($row = $result->fetchAssoziative()){ + $menu[] = $row["header"]; + } + return $menu; } public function getBreadcrumbsMenu(array $originalRootLine, array $configuration): array From cb10f96489ec9b2685628fc7346c249594b167ee Mon Sep 17 00:00:00 2001 From: bjoern Date: Mon, 30 Oct 2023 09:27:21 +0100 Subject: [PATCH 3/6] Added AnchorMenu --- Classes/Compiler/AnchorMenuCompiler.php | 65 +++++++++++++++++++ .../ContentObject/AnchorMenuContentObject.php | 58 +++++++++++++++++ .../ContentObjectServiceContainer.php | 18 +++-- Classes/DataProcessing/AnchorMenu.php | 55 ++++++++++++++++ Classes/Domain/Repository/MenuRepository.php | 21 ++++-- Configuration/Services.yaml | 6 ++ ext_localconf.php | 1 + 7 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 Classes/Compiler/AnchorMenuCompiler.php create mode 100644 Classes/ContentObject/AnchorMenuContentObject.php create mode 100644 Classes/DataProcessing/AnchorMenu.php diff --git a/Classes/Compiler/AnchorMenuCompiler.php b/Classes/Compiler/AnchorMenuCompiler.php new file mode 100644 index 0000000..2d77b79 --- /dev/null +++ b/Classes/Compiler/AnchorMenuCompiler.php @@ -0,0 +1,65 @@ +stdWrap($configuration['includeRootPages'] ?? false, $configuration['includeRootPages.'] ?? []); + $cacheIdentifier = $this->generateCacheIdentifierForMenu('anchor', $configuration); + $excludePages = $this->parseStdWrap($configuration['excludePages'] ?? '', $configuration['excludePages.'] ?? []); + $configuration['excludePages'] = $excludePages; + $depth = (int)$contentObjectRenderer->stdWrap($configuration['depth'] ?? 1, $configuration['depth.'] ?? []); + + + $pageIds = $contentObjectRenderer->stdWrap($configuration['pages'] ?? $this->getPageIds($this->menuRepository->getSubPagesOfPage($this->getCurrentSite()->getRootPageId(), $depth, $configuration)), $configuration['pages.'] ?? []); + $pageIds = GeneralUtility::intExplode(',', (string)$pageIds); + + $cacheIdentifier .= '-' . substr(md5(json_encode([$pageIds])), 0, 10); + + return $this->cache->get($cacheIdentifier, function () use ($configuration, $pageIds) { + $pages = []; + foreach ($pageIds as $pageId) { + $page = $this->menuRepository->getPage($pageId, $configuration); + $links = $this->menuRepository->getAnchorMenu($pageId, $configuration); + $page["anchors"] = $links; + if (!empty($page)) { + $pages[$pageId] = $page; + } + } + return $pages; + }); + } + + /** + * Get page ids from rootline + depth + * + * @param $pageArr + * @return string + */ + public function getPageIds($pageArr) + { + $pageIds = []; + foreach ($pageArr as $page) { + $pageIds[] = $page["uid"]; + } + return implode(",", $pageIds); + } +} diff --git a/Classes/ContentObject/AnchorMenuContentObject.php b/Classes/ContentObject/AnchorMenuContentObject.php new file mode 100644 index 0000000..fa17e54 --- /dev/null +++ b/Classes/ContentObject/AnchorMenuContentObject.php @@ -0,0 +1,58 @@ +getMajorVersion() < 12) { + parent::__construct($cObj); + } + $this->anchorMenuCompiler = (GeneralUtility::makeInstance(ContentObjectServiceContainer::class))->getAnchorMenuCompiler(); + } + + /** + * @param array $conf + * @return string + */ + public function render($conf = []) + { + $pages = $this->anchorMenuCompiler->compile($this->cObj, $conf); + $content = $this->renderItems($pages, $conf); + return $this->cObj->stdWrap($content, $conf); + } + + protected function renderItems(array $pages, array $conf): string + { + $content = ''; + $cObjForItems = GeneralUtility::makeInstance(ContentObjectRenderer::class); + foreach ($pages as $page) { + PageStateMarker::markStates($page); + $cObjForItems->start($page, 'pages'); + $content .= $cObjForItems->cObjGetSingle($conf['renderObj'] ?? '', $conf['renderObj.'] ?? []); + } + return $content; + } +} diff --git a/Classes/ContentObject/ContentObjectServiceContainer.php b/Classes/ContentObject/ContentObjectServiceContainer.php index 5f595f8..bd72c91 100644 --- a/Classes/ContentObject/ContentObjectServiceContainer.php +++ b/Classes/ContentObject/ContentObjectServiceContainer.php @@ -14,6 +14,7 @@ use B13\Menus\Compiler\LanguageMenuCompiler; use B13\Menus\Compiler\ListMenuCompiler; +use B13\Menus\Compiler\AnchorMenuCompiler; use B13\Menus\Compiler\TreeMenuCompiler; use B13\Menus\Domain\Repository\MenuRepository; use TYPO3\CMS\Core\SingletonInterface; @@ -26,17 +27,21 @@ class ContentObjectServiceContainer implements SingletonInterface protected LanguageMenuCompiler $languageMenuCompiler; protected MenuRepository $menuRepository; protected ListMenuCompiler $listMenuCompiler; + protected AnchorMenuCompiler $anchorMenuCompiler; protected TreeMenuCompiler $treeMenuCompiler; public function __construct( LanguageMenuCompiler $languageMenuCompiler, - MenuRepository $menuRepository, - ListMenuCompiler $listMenuCompiler, - TreeMenuCompiler $treeMenuCompiler - ) { + MenuRepository $menuRepository, + ListMenuCompiler $listMenuCompiler, + AnchorMenuCompiler $anchorMenuCompiler, + TreeMenuCompiler $treeMenuCompiler + ) + { $this->languageMenuCompiler = $languageMenuCompiler; $this->menuRepository = $menuRepository; $this->listMenuCompiler = $listMenuCompiler; + $this->anchorMenuCompiler = $anchorMenuCompiler; $this->treeMenuCompiler = $treeMenuCompiler; } @@ -55,6 +60,11 @@ public function getListMenuCompiler(): ListMenuCompiler return $this->listMenuCompiler; } + public function getAnchorMenuCompiler(): AnchorMenuCompiler + { + return $this->anchorMenuCompiler; + } + public function getTreeMenuCompiler(): TreeMenuCompiler { return $this->treeMenuCompiler; diff --git a/Classes/DataProcessing/AnchorMenu.php b/Classes/DataProcessing/AnchorMenu.php new file mode 100644 index 0000000..cdc5ec6 --- /dev/null +++ b/Classes/DataProcessing/AnchorMenu.php @@ -0,0 +1,55 @@ +anchorMenuCompiler = $anchorMenuCompiler; + parent::__construct($contentDataProcessor); + } + + /** + * @inheritDoc + */ + public function process(ContentObjectRenderer $cObj, array $contentObjectConfiguration, array $processorConfiguration, array $processedData) + { + if (isset($processorConfiguration['if.']) && !$cObj->checkIf($processorConfiguration['if.'])) { + return $processedData; + } + + $pages = $this->anchorMenuCompiler->compile($cObj, $processorConfiguration); + + foreach ($pages as &$page) { + PageStateMarker::markStates($page); + } + foreach ($pages as &$page) { + $this->processAdditionalDataProcessors($page, $processorConfiguration); + } + $targetVariableName = $cObj->stdWrapValue('as', $processorConfiguration); + $processedData[$targetVariableName] = $pages; + + return $processedData; + } +} diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index 8937f40..d7a84bd 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -1,6 +1,7 @@ context = $context; $this->pageRepository = $pageRepository; @@ -46,22 +48,26 @@ public function __construct(Context $context, PageRepository $pageRepository, Ev public function getAnchorMenu(int $pageId, array $configuration): array { + //@TODO add configuration options like e.g. filter + + //Get the queryBuilder for tt_content $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('tt_content'); - $result = $queryBuilder ->select("header") ->from("tt_content") - ->where($queryBuilder->exp()->eq("pid", $queryBuilder->createNamedParameter($pageId))) - ->andWhere($queryBuilder->exp()->neq("delete", 1)) + ->where($queryBuilder->expr()->eq("pid", $queryBuilder->createNamedParameter($pageId))) + ->andWhere($queryBuilder->expr()->eq("deleted", 0)) + ->andWhere($queryBuilder->expr()->eq("CType", $queryBuilder->createNamedParameter("header"))) ->orderBy("sorting") ->executeQuery(); $menu = []; - while($row = $result->fetchAssoziative()){ + while ($row = $result->fetchAssociative()) { $menu[] = $row["header"]; } + return $menu; } @@ -168,6 +174,7 @@ public function getSubPagesOfPage(int $pageId, int $depth, array $configuration) 'AND doktype NOT IN (' . implode(',', $excludedDoktypes) . ') ' . $whereClause, false ); + /** @var LanguageAspect $languageAspect */ $languageAspect = $this->context->getAspect('language'); foreach ($pageTree as $k => &$page) { @@ -176,7 +183,7 @@ public function getSubPagesOfPage(int $pageId, int $depth, array $configuration) continue; } if ($depth > 0) { - $page['subpages'] = $this->getSubPagesOfPage((int)$page['uid'], $depth-1, $configuration); + $page['subpages'] = $this->getSubPagesOfPage((int)$page['uid'], $depth - 1, $configuration); } $this->populateAdditionalKeysForPage($page); } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index cf0247c..f296226 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -13,6 +13,8 @@ services: public: true B13\Menus\DataProcessing\ListMenu: public: true + B13\Menus\DataProcessing\AnchorMenu: + public: true B13\Menus\DataProcessing\TreeMenu: public: true B13\Menus\ContentObject\ContentObjectServiceContainer: @@ -31,6 +33,10 @@ services: tags: - name: frontend.contentobject identifier: 'LISTMENU' + B13\Menus\ContentObject\AnchorMenuContentObject: + tags: + - name: frontend.contentobject + identifier: 'ANCHORMENU' B13\Menus\ContentObject\LanguageMenuContentObject: tags: - name: frontend.contentobject diff --git a/ext_localconf.php b/ext_localconf.php index 830c563..701ca5b 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -6,6 +6,7 @@ $GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'] = array_merge($GLOBALS['TYPO3_CONF_VARS']['FE']['ContentObjects'], [ 'TREEMENU' => \B13\Menus\ContentObject\TreeMenuContentObject::class, 'LISTMENU' => \B13\Menus\ContentObject\ListMenuContentObject::class, + 'ANCHORMENU' => \B13\Menus\ContentObject\AnchorMenuContentObject::class, 'LANGUAGEMENU' => \B13\Menus\ContentObject\LanguageMenuContentObject::class, 'BREADCRUMBS' => \B13\Menus\ContentObject\BreadcrumbsContentObject::class, ]); From 7e59ea76163d744fd5e5ba4a33e627cbdb9a1460 Mon Sep 17 00:00:00 2001 From: bjoern Date: Tue, 31 Oct 2023 09:11:20 +0100 Subject: [PATCH 4/6] Added HelperFunction and AnchorViewHelper.php. Added Anchor related part to Readme.md --- Classes/Compiler/AnchorMenuCompiler.php | 2 +- Classes/Domain/Repository/MenuRepository.php | 7 +- Classes/Helpers/HelperFunctions.php | 24 +++++ Classes/ViewHelpers/AnchorViewHelper.php | 32 ++++++ README.md | 101 ++++++++++++++----- 5 files changed, 136 insertions(+), 30 deletions(-) create mode 100644 Classes/Helpers/HelperFunctions.php create mode 100644 Classes/ViewHelpers/AnchorViewHelper.php diff --git a/Classes/Compiler/AnchorMenuCompiler.php b/Classes/Compiler/AnchorMenuCompiler.php index 2d77b79..a2142ec 100644 --- a/Classes/Compiler/AnchorMenuCompiler.php +++ b/Classes/Compiler/AnchorMenuCompiler.php @@ -22,7 +22,7 @@ class AnchorMenuCompiler extends AbstractMenuCompiler */ public function compile(ContentObjectRenderer $contentObjectRenderer, array $configuration): array { - $includeStartPageIds = $contentObjectRenderer->stdWrap($configuration['includeRootPages'] ?? false, $configuration['includeRootPages.'] ?? []); + $cacheIdentifier = $this->generateCacheIdentifierForMenu('anchor', $configuration); $excludePages = $this->parseStdWrap($configuration['excludePages'] ?? '', $configuration['excludePages.'] ?? []); $configuration['excludePages'] = $excludePages; diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index d7a84bd..512169d 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -13,6 +13,7 @@ */ use B13\Menus\Event\PopulatePageInformationEvent; +use B13\Menus\Helpers\HelperFunctions; use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\LanguageAspect; @@ -65,12 +66,16 @@ public function getAnchorMenu(int $pageId, array $configuration): array $menu = []; while ($row = $result->fetchAssociative()) { - $menu[] = $row["header"]; + $tmp = []; + $tmp["title"] = $row["header"]; + $tmp["id"] = HelperFunctions::getAnchorId($row["header"]); + $menu[] = $tmp; } return $menu; } + public function getBreadcrumbsMenu(array $originalRootLine, array $configuration): array { $pages = []; diff --git a/Classes/Helpers/HelperFunctions.php b/Classes/Helpers/HelperFunctions.php new file mode 100644 index 0000000..16c5ae8 --- /dev/null +++ b/Classes/Helpers/HelperFunctions.php @@ -0,0 +1,24 @@ +registerArgument('title', 'string', 'The string which should be converted to be used as an html identifier', true); + } + + public static function renderStatic( + array $arguments, + \Closure $renderChildrenClosure, + RenderingContextInterface $renderingContext + ) + { + $title = $renderChildrenClosure(); + return HelperFunctions::getAnchorId($title); + } + +} diff --git a/README.md b/README.md index 986f7d4..43b10a8 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ## Introduction TYPO3 CMS is known for handling large websites with lots of content. TYPO3 Core provides several ways to build -navigation / menus in a very flexible way. However, generating menus has been a tedious issue in most of our -large-scale projects. With TYPO3 v9, the performance of generating menus improved when it comes to URL generation, -but a few conceptual issues within linking and menu generation still exist: +navigation / menus in a very flexible way. However, generating menus has been a tedious issue in most of our large-scale +projects. With TYPO3 v9, the performance of generating menus improved when it comes to URL generation, but a few +conceptual issues within linking and menu generation still exist: 1. All logic relies on HMENU @@ -17,32 +17,31 @@ but a few conceptual issues within linking and menu generation still exist: 2. HMENU saves states for each page HMENU offers the possibility to define A LOT of states ("active", "current", "has children"). This information is - different for each page - obviously - which is then cached in a separate cache entry in `cache_hash` - making - the cache entries fairly large even though we do not use states. + different for each page - obviously - which is then cached in a separate cache entry in `cache_hash` - making the + cache entries fairly large even though we do not use states. - We use `expAll` (expand all subpages for all other pages as well) which makes the requests to the pages - enormously large. + We use `expAll` (expand all subpages for all other pages as well) which makes the requests to the pages enormously + large. 3. HMENU has a cryptic syntax for "special" menus - Nowadays, it is fairly common to build menus for footer navigation, mega-menus, sitemap-like menus for an additional - sidebar. Using "special." for language menus, for "directories" or just a simple list of pages, seems rather complex. - + Nowadays, it is fairly common to build menus for footer navigation, mega-menus, sitemap-like menus for an additional + sidebar. Using "special." for language menus, for "directories" or just a simple list of pages, seems rather complex. This extension tries to overcome these pitfalls by - * building menus once, then caches the results and afterwards applying active states (reduce amount of cached data). - This is especially important for Tree-based menus, - * introducing new cObjects and DataProcessors for the specific use cases making them more understandable for - non-TYPO3-Gurus. + +* building menus once, then caches the results and afterwards applying active states (reduce amount of cached data). + This is especially important for Tree-based menus, +* introducing new cObjects and DataProcessors for the specific use cases making them more understandable for + non-TYPO3-Gurus. ## Installation & Requirements Use `composer req b13/menus` or install it via TYPO3's Extension Manager from the [TYPO3 Extension Repository](https://extensions.typo3.org) using the extension key `menus`. -You need TYPO3 v9 with Site Handling for this extension to work. If your project supports mount points, -this is not implemented. In addition, pages to access restricted pages (even though no access exists) are not yet -considered. +You need TYPO3 v9 with Site Handling for this extension to work. If your project supports mount points, this is not +implemented. In addition, pages to access restricted pages (even though no access exists) are not yet considered. ## Features @@ -51,7 +50,8 @@ The extension ships TypoScript cObjects and TypoScript DataProcessors for Fluid- ### Common Options for all menus * excludePages - a list of page IDs (and their subpages if Tree Menu or Breadcrumbs is used) to exclude from the page -* excludeDoktypes - a list of doktypes that are not rendered. BE_USER_SECTIONs are excluded by default. SYS_FOLDERs are queried (for subpages etc) but never rendered. +* excludeDoktypes - a list of doktypes that are not rendered. BE_USER_SECTIONs are excluded by default. SYS_FOLDERs are + queried (for subpages etc) but never rendered. * includeNotInMenu - include pages with nav_hide set to 1, instead of ignoring them ### Common options for items @@ -188,7 +188,6 @@ Usage in Fluid: - ### Breadcrumb Menu (a.k.a. Rootline Menu) page.10 = BREADCRUMBS @@ -200,7 +199,6 @@ Usage in Fluid: page.10.renderObj.typolink.parameter.data = field:uid page.10.renderObj.wrap =
  • |
  • - Fluid-based solution: page.10 = FLUIDTEMPLATE @@ -219,9 +217,53 @@ Usage in Fluid: +### Anchor Menu + +Only basic implementation yet. No filter atm. means only CType "header" will be used for an anchor in the menu. You can +change this behavior in Classes\Domain\Repository\MenuRepository.php -> getAnchorMenu method in the where clause. + +Parameters are:
    +pages => for a list of Typo3 pages which should be scanned and will be used in generated links. if unset level 1 under +root will be used
    +excludePages => to exclude certain pages
    + +There is an AnchorViewHelper to assist with the HTML ID sanitization. + +Fluid-based solution: + + page.10 = FLUIDTEMPLATE + page.10.dataProcessing.10 = B13\Menus\DataProcessing\AnchorMenu + page.10.dataProcessing.10.as = breadcrumbs + +Usage in Fluid: + + + +Viewhelper: +`{namespace menu=B13\Menus\ViewHelpers}` + + + ### Dynamic configuration values for the menu (stdWrap) -If you want to get a menu of the direct siblings of a page, no matter what page you have selected, you can use the stdWrap functions built into each property: +If you want to get a menu of the direct siblings of a page, no matter what page you have selected, you can use the +stdWrap functions built into each property: 9999 = B13\Menus\DataProcessing\TreeMenu 9999 { @@ -229,20 +271,20 @@ If you want to get a menu of the direct siblings of a page, no matter what page as = listOfJobPages } -By using the `.data` property of the `entryPoints` attribute we can access each property of the currently build page. And so we can render the siblings of the page. +By using the `.data` property of the `entryPoints` attribute we can access each property of the currently build page. +And so we can render the siblings of the page. ## Technical Details ### Caching -Fetching the records is cached in a cache entry (with proper cache tags) within "cache_hash", -and the rendering is also cached in a separated cache entry within "cache_pages" for each page (regular), -where active state is applied. +Fetching the records is cached in a cache entry (with proper cache tags) within "cache_hash", and the rendering is also +cached in a separated cache entry within "cache_pages" for each page (regular), where active state is applied. ### FAQ -This extension refrains from handling options `addQueryParams`, or `ADD_GET_PARAM`, or the `target` property -in order to deal with the pages as "native" as possible, like any other link. +This extension refrains from handling options `addQueryParams`, or `ADD_GET_PARAM`, or the `target` property in order to +deal with the pages as "native" as possible, like any other link. ## License @@ -253,6 +295,7 @@ The extension is licensed under GPL v2+, same as the TYPO3 Core. For details see If you find an issue, feel free to create an issue on GitHub or a pull request. ### ToDos + - add `includeSpacer` option - extract stdWrap functionality out of caching parameters @@ -260,4 +303,6 @@ If you find an issue, feel free to create an issue on GitHub or a pull request. This extension was created by [Benni Mack](https://github.com/bmack) in 2019 for [b13 GmbH](https://b13.com). -[Find more TYPO3 extensions we have developed](https://b13.com/useful-typo3-extensions-from-b13-to-you) that help us deliver value in client projects. As part of the way we work, we focus on testing and best practices to ensure long-term performance, reliability, and results in all our code. +[Find more TYPO3 extensions we have developed](https://b13.com/useful-typo3-extensions-from-b13-to-you) that help us +deliver value in client projects. As part of the way we work, we focus on testing and best practices to ensure long-term +performance, reliability, and results in all our code. From 32946a25b19df6548d340cd79c3ec128a9104dee Mon Sep 17 00:00:00 2001 From: bjoern Date: Tue, 31 Oct 2023 21:39:45 +0100 Subject: [PATCH 5/6] Added tca checkbox toggle to show an anchor. Added tca nav title field to use a different title in the navigation e.g. a shorter one. --- Classes/Domain/Repository/MenuRepository.php | 6 ++- Configuration/TCA/Overrides/tt_content.php | 48 ++++++++++++++++++++ ext_tables.sql | 5 ++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Configuration/TCA/Overrides/tt_content.php create mode 100644 ext_tables.sql diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index 512169d..b273672 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -56,10 +56,11 @@ public function getAnchorMenu(int $pageId, array $configuration): array $queryBuilder = $this->connectionPool ->getQueryBuilderForTable('tt_content'); $result = $queryBuilder - ->select("header") + ->select("header", "tx_menus_anchor_nav_title") ->from("tt_content") ->where($queryBuilder->expr()->eq("pid", $queryBuilder->createNamedParameter($pageId))) ->andWhere($queryBuilder->expr()->eq("deleted", 0)) + ->andWhere($queryBuilder->expr()->eq("tx_menus_show_in_anchor_menu", 1)) ->andWhere($queryBuilder->expr()->eq("CType", $queryBuilder->createNamedParameter("header"))) ->orderBy("sorting") ->executeQuery(); @@ -67,8 +68,11 @@ public function getAnchorMenu(int $pageId, array $configuration): array $menu = []; while ($row = $result->fetchAssociative()) { $tmp = []; + $navTitle = $row["tx_menus_anchor_nav_title"]; + $tmp["title"] = $row["header"]; $tmp["id"] = HelperFunctions::getAnchorId($row["header"]); + $tmp["nav_title"] = $navTitle; $menu[] = $tmp; } diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php new file mode 100644 index 0000000..bbb334a --- /dev/null +++ b/Configuration/TCA/Overrides/tt_content.php @@ -0,0 +1,48 @@ + [ + 'exclude' => 0, + 'label' => 'Nav Title', + 'config' => [ + 'type' => 'input', + 'renderType' => 'input', + 'size' => 50, + 'max' => 100, + 'eval' => 'trim', + ], + ], + 'tx_menus_show_in_anchor_menu' => [ + 'label' => 'Show in anchor menu', + 'config' => [ + 'type' => 'check', + 'renderType' => 'checkboxToggle', + 'default' => 0, + ], + ], + ], +); + + +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( + 'tt_content', + 'tx_menus_anchor_nav_title', + 'header', + 'after:header' +); + +\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes( + 'tt_content', + 'tx_menus_show_in_anchor_menu', + 'header', + 'after:header' +); + + + diff --git a/ext_tables.sql b/ext_tables.sql new file mode 100644 index 0000000..a127907 --- /dev/null +++ b/ext_tables.sql @@ -0,0 +1,5 @@ +CREATE TABLE tt_content +( + tx_menus_anchor_nav_title varchar(100) DEFAULT '' NOT NULL, + tx_menus_show_in_anchor_menu tinyint(4) DEFAULT '0' NOT NULL +); From 152b28c5c7cb276fe60cfe570307d063b07c1a89 Mon Sep 17 00:00:00 2001 From: bjoern Date: Thu, 9 May 2024 09:28:33 +0200 Subject: [PATCH 6/6] Added tca checkbox toggle to show an anchor. Added tca nav title field to use a different title in the navigation e.g. a shorter one. --- Classes/Domain/Repository/MenuRepository.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Classes/Domain/Repository/MenuRepository.php b/Classes/Domain/Repository/MenuRepository.php index b273672..1b35a80 100644 --- a/Classes/Domain/Repository/MenuRepository.php +++ b/Classes/Domain/Repository/MenuRepository.php @@ -60,6 +60,7 @@ public function getAnchorMenu(int $pageId, array $configuration): array ->from("tt_content") ->where($queryBuilder->expr()->eq("pid", $queryBuilder->createNamedParameter($pageId))) ->andWhere($queryBuilder->expr()->eq("deleted", 0)) + ->andWhere($queryBuilder->expr()->eq("hidden", 0)) ->andWhere($queryBuilder->expr()->eq("tx_menus_show_in_anchor_menu", 1)) ->andWhere($queryBuilder->expr()->eq("CType", $queryBuilder->createNamedParameter("header"))) ->orderBy("sorting")