diff --git a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php similarity index 74% rename from app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php rename to app/code/Magento/Catalog/Plugin/Block/Topmenu.php index 608c7ee74b7cdda6409432f968734f2d1171a088..098b3282a1b107e56703ee4889f9ce005f25d223 100644 --- a/app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php +++ b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php @@ -3,17 +3,16 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Catalog\Observer; +namespace Magento\Catalog\Plugin\Block; use Magento\Catalog\Model\Category; use Magento\Framework\Data\Collection; use Magento\Framework\Data\Tree\Node; -use Magento\Framework\Event\ObserverInterface; /** - * Observer that add Categories Tree to Topmenu + * Plugin for top menu block */ -class AddCatalogToTopmenuItemsObserver implements ObserverInterface +class Topmenu { /** * Catalog category @@ -38,11 +37,11 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface private $layerResolver; /** + * Initialize dependencies. + * * @param \Magento\Catalog\Helper\Category $catalogCategory - * @param \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState * @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Catalog\Helper\Category $catalogCategory * @param \Magento\Catalog\Model\Layer\Resolver $layerResolver */ public function __construct( @@ -58,26 +57,27 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface } /** - * Checking whether the using static urls in WYSIWYG allowed event + * Build category tree for menu block. * - * @param \Magento\Framework\Event\Observer $observer + * @param \Magento\Theme\Block\Html\Topmenu $subject + * @param string $outermostClass + * @param string $childrenWrapClass + * @param int $limit * @return void + * @SuppressWarnings("PMD.UnusedFormalParameter") */ - public function execute(\Magento\Framework\Event\Observer $observer) - { - $block = $observer->getEvent()->getBlock(); - $menuRootNode = $observer->getEvent()->getMenu(); - $block->addIdentity(Category::CACHE_TAG); - + 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 => $menuRootNode]; // use nodes stack to avoid recursion + $mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion foreach ($collection as $category) { if (!isset($mapping[$category->getParentId()])) { continue; @@ -94,8 +94,28 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface $parentCategoryNode->addChild($categoryNode); $mapping[$category->getId()] = $categoryNode; //add node in stack + } + } - $block->addIdentity(Category::CACHE_TAG . '_' . $category->getId()); + /** + * 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()); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php similarity index 81% rename from app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php rename to app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php index 393cf8223d2a2d40ed54802515cdc91fa5fc804a..e0fe2deb232f68b989abb72463268d531e5e81cd 100644 --- a/app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php @@ -6,16 +6,16 @@ // @codingStandardsIgnoreFile -namespace Magento\Catalog\Test\Unit\Observer; +namespace Magento\Catalog\Test\Unit\Plugin\Block; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; -class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase +class TopmenuTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver + * @var \Magento\Catalog\Plugin\Block\Topmenu */ - protected $_observer; + protected $block; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Helper\Category @@ -100,8 +100,8 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase $collection->expects($this->once())->method('getIterator') ->willReturn(new \ArrayIterator([])); - $this->_observer = (new ObjectManager($this))->getObject( - 'Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver', + $this->block = (new ObjectManager($this))->getObject( + \Magento\Catalog\Plugin\Block\Topmenu::class, [ 'catalogCategory' => $this->_catalogCategory, 'menuCategoryData' => $this->menuCategoryData, @@ -142,23 +142,11 @@ class AddCatalogToTopmenuItemsObserverTest extends \PHPUnit_Framework_TestCase ); $blockMock = $this->_getCleanMock('\Magento\Theme\Block\Html\Topmenu'); - - $eventMock = $this->getMock('\Magento\Framework\Event', ['getBlock'], [], '', false); - $eventMock->expects($this->once()) - ->method('getBlock') - ->will($this->returnValue($blockMock)); - - $observerMock = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent', 'getMenu'], [], '', false); - $observerMock->expects($this->any()) - ->method('getEvent') - ->will($this->returnValue($eventMock)); - - return $observerMock; + return $blockMock; } public function testAddCatalogToTopMenuItems() { - $observer = $this->_preparationData(); - $this->_observer->execute($observer); + $this->block->beforeGetHtml($this->_preparationData()); } } diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 19a4f22a3c8e9425d474873f321f08baf062113c..78e46f0c39205ee7172c890739fa60a23946affa 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -46,6 +46,9 @@ <type name="Magento\Customer\Model\ResourceModel\Visitor"> <plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" /> </type> + <type name="Magento\Theme\Block\Html\Topmenu"> + <plugin name="catalogTopmenu" type="Magento\Catalog\Plugin\Block\Topmenu" /> + </type> <type name="Magento\Framework\Mview\View\StateInterface"> <plugin name="setStatusForMview" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\MviewState" /> </type> diff --git a/app/code/Magento/Catalog/etc/frontend/events.xml b/app/code/Magento/Catalog/etc/frontend/events.xml index afb3c70a14ade23fc8caab37ab4f3b564ae1f917..5ef8c724683141c38d735fcd0e321615d562ce6a 100644 --- a/app/code/Magento/Catalog/etc/frontend/events.xml +++ b/app/code/Magento/Catalog/etc/frontend/events.xml @@ -12,7 +12,4 @@ <event name="customer_logout"> <observer name="catalog" instance="Magento\Catalog\Observer\Compare\BindCustomerLogoutObserver" shared="false" /> </event> - <event name="page_block_html_topmenu_gethtml_before"> - <observer name="catalog_add_topmenu_items" instance="Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver" /> - </event> </config> diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php index d0205f51453bc4d003e6347af7b5754ac40d6d4c..52a4714fea8db053b49790a548538644866744cc 100644 --- a/app/code/Magento/Theme/Block/Html/Topmenu.php +++ b/app/code/Magento/Theme/Block/Html/Topmenu.php @@ -330,7 +330,9 @@ class Topmenu extends Template implements IdentityInterface */ public function addIdentity($identity) { - $this->identities[] = $identity; + if (!in_array($identity, $this->identities)) { + $this->identities[] = $identity; + } } /** @@ -364,4 +366,14 @@ class Topmenu extends Template implements IdentityInterface { return array_merge(parent::getCacheTags(), $this->getIdentities()); } + + /** + * Get menu object. + * + * @return Node + */ + public function getMenu() + { + return $this->_menu; + } }