diff --git a/app/code/Magento/Catalog/Plugin/Block/Topmenu.php b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php
index b4aa5bd960b..3a76c554aa0 100644
--- a/app/code/Magento/Catalog/Plugin/Block/Topmenu.php
+++ b/app/code/Magento/Catalog/Plugin/Block/Topmenu.php
@@ -12,13 +12,12 @@
use Magento\Framework\Data\Tree\Node;
/**
- * Plugin for top menu block
+ * Plugin that enhances the top menu block by building and managing the category tree
+ * for menu rendering in a storefront.
*/
class Topmenu
{
/**
- * Catalog category
- *
* @var \Magento\Catalog\Helper\Category
*/
protected $catalogCategory;
@@ -33,29 +32,21 @@ class Topmenu
*/
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
+ \Magento\Store\Model\StoreManagerInterface $storeManager
) {
$this->catalogCategory = $catalogCategory;
$this->collectionFactory = $categoryCollectionFactory;
$this->storeManager = $storeManager;
- $this->layerResolver = $layerResolver;
}
/**
@@ -78,7 +69,6 @@ public function beforeGetHtml(
$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();
@@ -97,7 +87,6 @@ public function beforeGetHtml(
$categoryNode = new Node(
$this->getCategoryAsArray(
$category,
- $currentCategory,
$category->getParentId() == $categoryParentId
),
'id',
@@ -132,39 +121,20 @@ public function beforeGetIdentities(\Magento\Theme\Block\Html\Topmenu $subject)
}
}
- /**
- * 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 Category $category
* @param bool $isParentActive
* @return array
*/
- private function getCategoryAsArray($category, $currentCategory, $isParentActive)
+ private function getCategoryAsArray($category, $isParentActive): array
{
$categoryId = $category->getId();
return [
'name' => $category->getName(),
'id' => 'category-node-' . $categoryId,
'url' => $this->catalogCategory->getCategoryUrl($category),
- 'has_active' => in_array((string)$categoryId, explode('/', (string)$currentCategory->getPath()), true),
- 'is_active' => $categoryId == $currentCategory->getId(),
'is_category' => true,
'is_parent_active' => $isParentActive
];
@@ -196,22 +166,4 @@ protected function getCategoryTree($storeId, $rootId)
return $collection;
}
-
- /**
- * Add active
- *
- * @param \Magento\Theme\Block\Html\Topmenu $subject
- * @param string[] $result
- * @return string[]
- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
- */
- public function afterGetCacheKeyInfo(\Magento\Theme\Block\Html\Topmenu $subject, array $result)
- {
- $activeCategory = $this->getCurrentCategory();
- if ($activeCategory) {
- $result[] = Category::CACHE_TAG . '_' . $activeCategory->getId();
- }
-
- return $result;
- }
}
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/SeoConfigData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/SeoConfigData.xml
new file mode 100644
index 00000000000..043955a6189
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/SeoConfigData.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ catalog/seo/product_use_categories
+ 0
+ Yes
+ 1
+
+
+ catalog/seo/product_use_categories
+ 0
+ No
+ 0
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
index de8b887cc26..f5fb74ab4eb 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
@@ -12,7 +12,9 @@
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeNoCategoryPathHtmlSuffixNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeNoCategoryPathHtmlSuffixNavigationTest.xml
new file mode 100644
index 00000000000..3008e280de8
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeNoCategoryPathHtmlSuffixNavigationTest.xml
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory1Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount
+ 1
+
+
+ $highlightedParentCategoryAmount
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class
+ has-active
+
+
+
+ $grabCategory_1_1_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try2
+ 1
+
+
+ $highlightedParentCategoryAmount_Try2
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try2
+ has-active
+
+
+
+ $grabCategory_1_1_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try3
+ 1
+
+
+ $highlightedParentCategoryAmount_Try3
+ 1
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try4
+ 0
+
+
+ $highlightedParentCategoryAmount_Try4
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try3
+ has-active
+
+
+
+ $grabCategory_1_2_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try5
+ 1
+
+
+ $highlightedParentCategoryAmount_Try5
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try4
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try6
+ 1
+
+
+ $highlightedParentCategoryAmount_Try6
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try5
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try3
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try7
+ 1
+
+
+ $highlightedParentCategoryAmount_Try7
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try8
+ 0
+
+
+ $highlightedParentCategoryAmount_Try8
+ 0
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeYesCategoryPathHtmlSuffixNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeYesCategoryPathHtmlSuffixNavigationTest.xml
new file mode 100644
index 00000000000..c131aee6e03
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontNoStoreCodeYesCategoryPathHtmlSuffixNavigationTest.xml
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory1Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount
+ 1
+
+
+ $highlightedParentCategoryAmount
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class
+ has-active
+
+
+
+ $grabCategory_1_1_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try2
+ 1
+
+
+ $highlightedParentCategoryAmount_Try2
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try2
+ has-active
+
+
+
+ $grabCategory_1_1_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try3
+ 1
+
+
+ $highlightedParentCategoryAmount_Try3
+ 1
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try4
+ 0
+
+
+ $highlightedParentCategoryAmount_Try4
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try3
+ has-active
+
+
+
+ $grabCategory_1_2_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try5
+ 1
+
+
+ $highlightedParentCategoryAmount_Try5
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try4
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try6
+ 1
+
+
+ $highlightedParentCategoryAmount_Try6
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try5
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try3
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try7
+ 1
+
+
+ $highlightedParentCategoryAmount_Try7
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try6
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try4
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try8
+ 1
+
+
+ $highlightedParentCategoryAmount_Try8
+ 1
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeNoCategoryPathNoSuffixNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeNoCategoryPathNoSuffixNavigationTest.xml
new file mode 100644
index 00000000000..d97bb47215f
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeNoCategoryPathNoSuffixNavigationTest.xml
@@ -0,0 +1,275 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory1Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount
+ 1
+
+
+ $highlightedParentCategoryAmount
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class
+ has-active
+
+
+
+ $grabCategory_1_1_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try2
+ 1
+
+
+ $highlightedParentCategoryAmount_Try2
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try2
+ has-active
+
+
+
+ $grabCategory_1_1_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try3
+ 1
+
+
+ $highlightedParentCategoryAmount_Try3
+ 1
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try4
+ 0
+
+
+ $highlightedParentCategoryAmount_Try4
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try3
+ has-active
+
+
+
+ $grabCategory_1_2_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try5
+ 1
+
+
+ $highlightedParentCategoryAmount_Try5
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try4
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try6
+ 1
+
+
+ $highlightedParentCategoryAmount_Try6
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try5
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try3
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try7
+ 1
+
+
+ $highlightedParentCategoryAmount_Try7
+ 1
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try8
+ 0
+
+
+ $highlightedParentCategoryAmount_Try8
+ 0
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeYesCategoryPathNoSuffixNavigationTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeYesCategoryPathNoSuffixNavigationTest.xml
new file mode 100644
index 00000000000..0069684b813
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/StorefrontYesStoreCodeYesCategoryPathNoSuffixNavigationTest.xml
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory1Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount
+ 1
+
+
+ $highlightedParentCategoryAmount
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class
+ has-active
+
+
+
+ $grabCategory_1_1_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try2
+ 1
+
+
+ $highlightedParentCategoryAmount_Try2
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try2
+ has-active
+
+
+
+ $grabCategory_1_1_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try3
+ 1
+
+
+ $highlightedParentCategoryAmount_Try3
+ 1
+
+
+
+
+
+
+
+
+
+ $highlightedCategoryAmount_Try4
+ 0
+
+
+ $highlightedParentCategoryAmount_Try4
+ 0
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try3
+ has-active
+
+
+
+ $grabCategory_1_2_Class
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try5
+ 1
+
+
+ $highlightedParentCategoryAmount_Try5
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try4
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try2
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try6
+ 1
+
+
+ $highlightedParentCategoryAmount_Try6
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try5
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try3
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try7
+ 1
+
+
+ $highlightedParentCategoryAmount_Try7
+ 1
+
+
+
+
+
+
+
+
+ $grabCategory_1_Class_Try6
+ has-active
+
+
+
+ $grabCategory_1_2_Class_Try4
+ active
+
+
+
+
+
+ $highlightedCategoryAmount_Try8
+ 1
+
+
+ $highlightedParentCategoryAmount_Try8
+ 1
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
index 7e2517e4a03..b50a4395209 100644
--- a/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Plugin/Block/TopmenuTest.php
@@ -8,8 +8,6 @@
namespace Magento\Catalog\Test\Unit\Plugin\Block;
use Magento\Catalog\Helper\Category;
-use Magento\Catalog\Model\Layer;
-use Magento\Catalog\Model\Layer\Resolver;
use Magento\Catalog\Model\ResourceModel\Category\Collection;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Category\StateDependentCollectionFactory;
@@ -42,16 +40,6 @@ class TopmenuTest extends TestCase
*/
protected $storeMock;
- /**
- * @var MockObject|Resolver
- */
- protected $layerResolverMock;
-
- /**
- * @var MockObject|Layer
- */
- protected $catalogLayerMock;
-
/**
* @var MockObject|CollectionFactory
*/
@@ -90,9 +78,7 @@ protected function setUp(): void
$this->childrenCategoryMock = $this->_getCleanMock(\Magento\Catalog\Model\Category::class);
$this->categoryHelperMock = $this->_getCleanMock(Category::class);
- $this->catalogLayerMock = $this->_getCleanMock(Layer::class);
$this->categoryMock = $this->_getCleanMock(\Magento\Catalog\Model\Category::class);
- $this->layerResolverMock = $this->_getCleanMock(Resolver::class);
$this->storeMock = $this->_getCleanMock(Store::class);
$this->storeManagerMock = $this->_getCleanMock(StoreManagerInterface::class);
$this->categoryCollectionMock = $this->_getCleanMock(
@@ -103,9 +89,6 @@ protected function setUp(): void
['create']
);
- $this->catalogLayerMock->expects($this->once())->method('getCurrentCategory')
- ->willReturn($this->childrenCategoryMock);
-
$this->storeManagerMock->expects($this->atLeastOnce())->method('getStore')
->willReturn($this->storeMock);
@@ -114,9 +97,6 @@ protected function setUp(): void
$this->categoryMock->expects($this->once())->method('getParentIds')
->willReturn($categoryParentIds);
- $this->layerResolverMock->expects($this->once())->method('get')
- ->willReturn($this->catalogLayerMock);
-
$this->storeMock->expects($this->once())->method('getRootCategoryId')
->willReturn($rootCategoryId);
@@ -131,8 +111,7 @@ protected function setUp(): void
[
'catalogCategory' => $this->categoryHelperMock,
'categoryCollectionFactory' => $this->categoryCollectionFactoryMock,
- 'storeManager' => $this->storeManagerMock,
- 'layerResolver' => $this->layerResolverMock,
+ 'storeManager' => $this->storeManagerMock
]
);
}
diff --git a/app/code/Magento/Theme/Block/Html/Topmenu.php b/app/code/Magento/Theme/Block/Html/Topmenu.php
index f8460b43ba2..37a2149d298 100644
--- a/app/code/Magento/Theme/Block/Html/Topmenu.php
+++ b/app/code/Magento/Theme/Block/Html/Topmenu.php
@@ -312,12 +312,6 @@ protected function _getMenuItemClasses(Node $item)
$classes[] = 'first';
}
- if ($item->getIsActive()) {
- $classes[] = 'active';
- } elseif ($item->getHasActive()) {
- $classes[] = 'has-active';
- }
-
if ($item->getIsLast()) {
$classes[] = 'last';
}
diff --git a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
index 59b3ca6f4f7..b5fe6ac1c30 100644
--- a/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
+++ b/app/code/Magento/Theme/Test/Unit/Block/Html/TopmenuTest.php
@@ -77,17 +77,10 @@ class TopmenuTest extends TestCase
private $requestMock;
// @codingStandardsIgnoreStart
-
/** @var string */
- protected $htmlWithoutCategory = <<
HTML;
-
- /** @var string */
- protected $htmlWithCategory = <<
-HTML;
-
// @codingStandardsIgnoreEnd
/**
@@ -143,7 +136,7 @@ public function testGetHtmlWithoutSelectedCategory(): void
$treeNode = $this->buildTree(false);
- $transportObject = new DataObject(['html' => $this->htmlWithoutCategory]);
+ $transportObject = new DataObject(['html' => $this->navigationMenuHtml]);
$this->eventManagerMock->expects($this->exactly(2))
->method('dispatch')
@@ -167,7 +160,7 @@ public function testGetHtmlWithoutSelectedCategory(): void
],
]);
- $this->assertEquals($this->htmlWithoutCategory, $topmenuBlock->getHtml());
+ $this->assertEquals($this->navigationMenuHtml, $topmenuBlock->getHtml());
}
/**
@@ -179,7 +172,7 @@ public function testGetHtmlWithSelectedCategory(): void
$treeNode = $this->buildTree(true);
- $transportObject = new DataObject(['html' => $this->htmlWithCategory]);
+ $transportObject = new DataObject(['html' => $this->navigationMenuHtml]);
$this->eventManagerMock->expects($this->exactly(2))
->method('dispatch')
@@ -203,7 +196,7 @@ public function testGetHtmlWithSelectedCategory(): void
],
]);
- $this->assertEquals($this->htmlWithCategory, $topmenuBlock->getHtml());
+ $this->assertEquals($this->navigationMenuHtml, $topmenuBlock->getHtml());
}
/**
@@ -236,7 +229,7 @@ public function testGetCacheKeyInfo(): void
* @param bool $isCurrentItem
* @return MockObject
*/
- private function buildTree($isCurrentItem): MockObject
+ private function buildTree(bool $isCurrentItem): MockObject
{
$treeMock = $this->getMockBuilder(Tree::class)
->disableOriginalConstructor()
diff --git a/lib/web/mage/menu.js b/lib/web/mage/menu.js
index ed958adf336..ea44a9450a5 100644
--- a/lib/web/mage/menu.js
+++ b/lib/web/mage/menu.js
@@ -16,6 +16,7 @@ define([
*/
$.widget('mage.menu', $.ui.menu, {
options: {
+ categoryLayoutClass: 'catalog-product-view',
responsive: false,
expanded: false,
showDelay: 42,
@@ -182,33 +183,77 @@ define([
},
/**
- * Tries to retrieve category URL from current URL and mark this category as active
- * @see _setActiveMenuForCategory(url)
+ * Extracts the URL extension from the given URL.
+ * It identifies the last segment of the URL after the last slash ('/') and returns the substring after the last dot ('.')
+ * If there's no dot in the last segment, it returns an empty string.
*
- * @example
- * currentUrl - http://magento.com/category1/category12/product.html,
- * category URLs has extensions .phtml - http://magento.com/category1.phtml
- * method sets active category which has URL http://magento.com/category1/category12.phtml
+ * @param {String} url - The URL from which to extract the extension.
+ * @return {String} The extracted URL extension or an empty string if no extension is found.
+ * @private
+ */
+ _getUrlExtension: function (url) {
+ var lastSegment = url.slice(url.lastIndexOf('/') + 1);
+ return lastSegment.includes('.') ? lastSegment.slice(lastSegment.lastIndexOf('.')) : '';
+ },
+
+ /**
+ * Determines if the current page is a product page.
+ * It checks the catalog product view related class in the body tag of the document.
+ *
+ * @return {Boolean} True if the current page is a product page, false otherwise.
+ * @private
+ */
+ _isProductPage: function () {
+ return document.body.classList.contains(this.options.categoryLayoutClass);
+ },
+
+ /**
+ * Sets the active state in the menu for a product page. Determines the category URL from either
+ * the referrer URL or the current URL, using the URL extension to identify the category.
+ * Sets the corresponding category as active in the menu if a valid category URL is found.
+ * Clears the active state if no valid category URL is found or if it's not a product page.
*
- * @param {String} currentUrl - current page URL without parameters
+ * @param {String} currentUrl - The current page URL without parameters.
* @return void
* @private
*/
_setActiveMenuForProduct: function (currentUrl) {
- var categoryUrlExtension,
- lastUrlSection,
- possibleCategoryUrl,
- //retrieve first category URL to know what extension is used for category URLs
- firstCategoryUrl = this.element.find('> li a').attr('href');
-
- if (firstCategoryUrl) {
- lastUrlSection = firstCategoryUrl.substr(firstCategoryUrl.lastIndexOf('/'));
- categoryUrlExtension = lastUrlSection.lastIndexOf('.') !== -1 ?
- lastUrlSection.substr(lastUrlSection.lastIndexOf('.')) : '';
-
- possibleCategoryUrl = currentUrl.substr(0, currentUrl.lastIndexOf('/')) + categoryUrlExtension;
- this._setActiveMenuForCategory(possibleCategoryUrl);
+ var firstCategoryUrl = this.element.find('> li a').attr('href');
+
+ if (!firstCategoryUrl) {
+ this._clearActiveState();
+ return;
}
+
+ var categoryUrlExtension = this._getUrlExtension(firstCategoryUrl);
+ var categoryUrl;
+ var isProductPage = this._isProductPage();
+
+ if (isProductPage) {
+ var currentHostname = window.location.hostname;
+
+ if (document.referrer.includes(currentHostname) && document.referrer.endsWith(categoryUrlExtension)) {
+ categoryUrl = document.referrer.split('?')[0];
+ } else {
+ categoryUrl = currentUrl.substring(0, currentUrl.lastIndexOf('/')) + categoryUrlExtension;
+ }
+
+ this._setActiveMenuForCategory(categoryUrl);
+ } else {
+ this._clearActiveState();
+ }
+ },
+
+ /**
+ * Clears the active state from all menu items within the navigation element.
+ * It removes 'active' and 'has-active' classes from all list items (li elements),
+ * which are used to indicate the currently selected or parent of a selected item.
+ *
+ * @return void
+ * @private
+ */
+ _clearActiveState: function () {
+ this.element.find('li').removeClass('active has-active');
},
/**