diff --git a/Block/Menu.php b/Block/Menu.php index 4b03b964..4bb20e0a 100644 --- a/Block/Menu.php +++ b/Block/Menu.php @@ -24,6 +24,7 @@ class Menu extends Template implements DataObject\IdentityInterface { const XML_SNOWMENU_GENERAL_CUSTOMER_GROUPS = 'snowmenu/general/customer_groups'; + const XML_SNOWMENU_GENERAL_CACHE_TAGS = 'snowmenu/general/cache_tags'; /** * @var MenuRepositoryInterface @@ -84,6 +85,11 @@ class Menu extends Template implements DataObject\IdentityInterface */ private $httpContext; + /** + * @var array + */ + private $nodeTypeCaches = []; + /** * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -97,6 +103,7 @@ public function __construct( ImageFile $imageFile, Escaper $escaper, Context $httpContext, + array $nodeTypeCaches = [], array $data = [] ) { parent::__construct($context, $data); @@ -110,6 +117,7 @@ public function __construct( $this->setTemplate($this->getMenuTemplate($this->_template)); $this->submenuTemplate = $this->getSubmenuTemplate(); $this->httpContext = $httpContext; + $this->nodeTypeCaches = $nodeTypeCaches; } /** @@ -119,11 +127,22 @@ public function __construct( */ public function getIdentities() { - return [ + $tags = [ \Snowdog\Menu\Model\Menu::CACHE_TAG . '_' . $this->loadMenu()->getId(), Block::CACHE_TAG, \Snowdog\Menu\Model\Menu::CACHE_TAG ]; + if (!$this->canGatherEntityCacheTags()) { + return $tags; + } + foreach ($this->nodeTypeCaches as $provider) { + $entityCacheTags = $this->nodeTypeProvider->getProvider($provider)->getEntityCacheTags(); + if (!empty($entityCacheTags)) { + $tags = array_merge($tags, $entityCacheTags); + } + } + + return $tags; } protected function getCacheLifetime() @@ -481,19 +500,11 @@ private function fetchData() } foreach ($types['category'] as $nodes) { - if ($nodes['node']->getContent() == 20) { - $nodes['node']->setHideCategoryIfEmpty(true); - } - /** @var \Snowdog\Menu\Block\NodeType\Category $categoryProvider */ - if (!$nodes['node']->getHideCategoryIfEmpty()) { - continue; - } $categoryProvider = $this->nodeTypeProvider->getProvider('category'); $productCount = $categoryProvider->getCategoryProductCount($nodes['node']->getNodeId()); if (empty($productCount)) { [$level, $parent, $idx] = $nodes['path']; unset ($this->nodes[$level][$parent][$idx]); - //todo unset children } } } @@ -530,6 +541,15 @@ private function getSubmenuTemplate() return $this->getMenuTemplate($baseSubmenuTemplate); } + private function canGatherEntityCacheTags() + { + if (!$this->_scopeConfig->isSetFlag(self::XML_SNOWMENU_GENERAL_CACHE_TAGS)) { + return false; + } + + return !empty($this->nodeTypeCaches); + } + public function getCustomerGroupId() { return $this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_GROUP); diff --git a/Block/NodeType/Category.php b/Block/NodeType/Category.php index 5d94aefa..5722ecb7 100644 --- a/Block/NodeType/Category.php +++ b/Block/NodeType/Category.php @@ -43,6 +43,10 @@ class Category extends AbstractNode * @var array */ private $categories; + /** + * @var array + */ + private $cacheTags; /** * @var array @@ -112,7 +116,8 @@ public function fetchData(array $nodes) $this->nodes, $this->categoryUrls, $this->categories, - $this->categoryProductCounts + $this->categoryProductCounts, + $this->cacheTags ] = $this->_categoryModel->fetchData($nodes, $storeId); } @@ -226,4 +231,9 @@ public function getLabel() { return __("Category"); } + + public function getEntityCacheTags() + { + return $this->cacheTags; + } } diff --git a/Model/NodeType/Category.php b/Model/NodeType/Category.php index 5c0193f4..e80ab876 100644 --- a/Model/NodeType/Category.php +++ b/Model/NodeType/Category.php @@ -123,10 +123,11 @@ public function fetchData(array $nodes, $storeId) $categoryUrls = $this->getResource()->fetchData($storeId, $categoryIds); $categories = $this->getCategories($storeId, $categoryIds); $categoryProductCounts = $this->getResource()->getCategoriesProductCount($categoryIds); + $cacheTags = preg_filter('/^/', 'cat_c_p' . '_', $categoryIds); $this->profiler->stop(__METHOD__); - return [$localNodes, $categoryUrls, $categories, $categoryProductCounts]; + return [$localNodes, $categoryUrls, $categories, $categoryProductCounts, $cacheTags]; } /** diff --git a/Model/ResourceModel/NodeType/Category.php b/Model/ResourceModel/NodeType/Category.php index bb6d4fb9..e269401c 100644 --- a/Model/ResourceModel/NodeType/Category.php +++ b/Model/ResourceModel/NodeType/Category.php @@ -15,6 +15,7 @@ use Magento\Framework\App\ResourceConnection; use Magento\Framework\EntityManager\MetadataPool; use Magento\Store\Model\Store; +use Zend_Db_Expr; class Category extends AbstractNode { @@ -111,15 +112,12 @@ public function getCategoriesProductCount($categoryIds = []) { $productTable = $this->getConnection()->getTableName('catalog_category_product'); - $select = $this->getConnection()->select()->from( - ['main_table' => $productTable], - ['main_table.category_id', new \Zend_Db_Expr('COUNT(main_table.product_id)')] - )->where( - 'main_table.category_id IN (?)', $categoryIds - )->group('main_table.category_id'); - - $counts = $this->getConnection()->fetchPairs($select); + $select = $this->getConnection() + ->select() + ->from($productTable, ['category_id', new Zend_Db_Expr('COUNT(product_id)')]) + ->where('category_id IN (?)', $categoryIds) + ->group('category_id'); - return $counts; + return $this->getConnection()->fetchPairs($select); } } diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 0cd14336..543dfb41 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -15,6 +15,11 @@ Controls serving different menus to different customer groups Magento\Config\Model\Config\Source\Yesno + + + Controls menu caching mechanisms. Enabling this will allow for gathering cache tags from menu nodes, which allows handling menus that are heavily dependent on e.g. category contents - see https://github.com/SnowdogApps/magento2-menu/discussions/317 + Magento\Config\Model\Config\Source\Yesno + diff --git a/etc/di.xml b/etc/di.xml index bf2f437f..c46b4223 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -74,4 +74,12 @@ Snowdog\Menu\Model\ImportExport\Processor\Import\Node\Validator\Proxy + + + + + category + + +