123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Catalog\Plugin\Block;
- use Magento\Catalog\Model\Category;
- use Magento\Framework\Data\Collection;
- use Magento\Framework\Data\Tree\Node;
- /**
- * Plugin for top menu block
- */
- class Topmenu
- {
- /**
- * Catalog category
- *
- * @var \Magento\Catalog\Helper\Category
- */
- protected $catalogCategory;
- /**
- * @var \Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory
- */
- private $collectionFactory;
- /**
- * @var \Magento\Store\Model\StoreManagerInterface
- */
- private $storeManager;
- /**
- * @var \Magento\Catalog\Model\Layer\Resolver
- */
- private $layerResolver;
- /**
- * Initialize dependencies.
- *
- * @param \Magento\Catalog\Helper\Category $catalogCategory
- * @param \Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory $categoryCollectionFactory
- * @param \Magento\Store\Model\StoreManagerInterface $storeManager
- * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver
- */
- public function __construct(
- \Magento\Catalog\Helper\Category $catalogCategory,
- \Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory $categoryCollectionFactory,
- \Magento\Store\Model\StoreManagerInterface $storeManager,
- \Magento\Catalog\Model\Layer\Resolver $layerResolver
- ) {
- $this->catalogCategory = $catalogCategory;
- $this->collectionFactory = $categoryCollectionFactory;
- $this->storeManager = $storeManager;
- $this->layerResolver = $layerResolver;
- }
- /**
- * Build category tree for menu block.
- *
- * @param \Magento\Theme\Block\Html\Topmenu $subject
- * @param string $outermostClass
- * @param string $childrenWrapClass
- * @param int $limit
- * @return void
- * @SuppressWarnings("PMD.UnusedFormalParameter")
- */
- public function beforeGetHtml(
- \Magento\Theme\Block\Html\Topmenu $subject,
- $outermostClass = '',
- $childrenWrapClass = '',
- $limit = 0
- ) {
- $rootId = $this->storeManager->getStore()->getRootCategoryId();
- $storeId = $this->storeManager->getStore()->getId();
- /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
- $collection = $this->getCategoryTree($storeId, $rootId);
- $currentCategory = $this->getCurrentCategory();
- $mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion
- foreach ($collection as $category) {
- $categoryParentId = $category->getParentId();
- if (!isset($mapping[$categoryParentId])) {
- $parentIds = $category->getParentIds();
- foreach ($parentIds as $parentId) {
- if (isset($mapping[$parentId])) {
- $categoryParentId = $parentId;
- }
- }
- }
- /** @var Node $parentCategoryNode */
- $parentCategoryNode = $mapping[$categoryParentId];
- $categoryNode = new Node(
- $this->getCategoryAsArray(
- $category,
- $currentCategory,
- $category->getParentId() == $categoryParentId
- ),
- 'id',
- $parentCategoryNode->getTree(),
- $parentCategoryNode
- );
- $parentCategoryNode->addChild($categoryNode);
- $mapping[$category->getId()] = $categoryNode; //add node in stack
- }
- }
- /**
- * Add list of associated identities to the top menu block for caching purposes.
- *
- * @param \Magento\Theme\Block\Html\Topmenu $subject
- * @return void
- */
- public function beforeGetIdentities(\Magento\Theme\Block\Html\Topmenu $subject)
- {
- $subject->addIdentity(Category::CACHE_TAG);
- $rootId = $this->storeManager->getStore()->getRootCategoryId();
- $storeId = $this->storeManager->getStore()->getId();
- /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
- $collection = $this->getCategoryTree($storeId, $rootId);
- $mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion
- foreach ($collection as $category) {
- if (!isset($mapping[$category->getParentId()])) {
- continue;
- }
- $subject->addIdentity(Category::CACHE_TAG . '_' . $category->getId());
- }
- }
- /**
- * Get current Category from catalog layer
- *
- * @return \Magento\Catalog\Model\Category
- */
- private function getCurrentCategory()
- {
- $catalogLayer = $this->layerResolver->get();
- if (!$catalogLayer) {
- return null;
- }
- return $catalogLayer->getCurrentCategory();
- }
- /**
- * Convert category to array
- *
- * @param \Magento\Catalog\Model\Category $category
- * @param \Magento\Catalog\Model\Category $currentCategory
- * @param bool $isParentActive
- * @return array
- */
- private function getCategoryAsArray($category, $currentCategory, $isParentActive)
- {
- return [
- 'name' => $category->getName(),
- 'id' => 'category-node-' . $category->getId(),
- 'url' => $this->catalogCategory->getCategoryUrl($category),
- 'has_active' => in_array((string)$category->getId(), explode('/', $currentCategory->getPath()), true),
- 'is_active' => $category->getId() == $currentCategory->getId(),
- 'is_category' => true,
- 'is_parent_active' => $isParentActive
- ];
- }
- /**
- * Get Category Tree
- *
- * @param int $storeId
- * @param int $rootId
- * @return \Magento\Catalog\Model\ResourceModel\Category\Collection
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function getCategoryTree($storeId, $rootId)
- {
- /** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
- $collection = $this->collectionFactory->create();
- $collection->setStoreId($storeId);
- $collection->addAttributeToSelect('name');
- $collection->addFieldToFilter('path', ['like' => '1/' . $rootId . '/%']); //load only from store root
- $collection->addAttributeToFilter('include_in_menu', 1);
- $collection->addIsActiveFilter();
- $collection->addNavigationMaxDepthFilter();
- $collection->addUrlRewriteToResult();
- $collection->addOrder('level', Collection::SORT_ORDER_ASC);
- $collection->addOrder('position', Collection::SORT_ORDER_ASC);
- $collection->addOrder('parent_id', Collection::SORT_ORDER_ASC);
- $collection->addOrder('entity_id', Collection::SORT_ORDER_ASC);
- return $collection;
- }
- }
|