Skip to content

Commit 6e3b2f9

Browse files
committed
Remove active category in the cache key
- Remove dependency to Catalog from Theme module; - Enhance menu.js logic;
1 parent 0fc4625 commit 6e3b2f9

File tree

8 files changed

+237
-197
lines changed

8 files changed

+237
-197
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\ViewModel;
9+
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\DataObject;
12+
use Magento\Framework\Serialize\Serializer\JsonHexTag;
13+
use Magento\Framework\View\Element\Block\ArgumentInterface;
14+
use Magento\Store\Model\ScopeInterface;
15+
16+
/**
17+
* ViewModel for SEO configurations in the top navigation menu.
18+
*/
19+
class SeoConfigTopMenu extends DataObject implements ArgumentInterface
20+
{
21+
private const XML_PATH_PRODUCT_USE_CATEGORIES = 'catalog/seo/product_use_categories';
22+
23+
/**
24+
* @var ScopeConfigInterface
25+
*/
26+
private ScopeConfigInterface $scopeConfig;
27+
28+
/**
29+
* @var JsonHexTag
30+
*/
31+
private JsonHexTag $jsonSerializer;
32+
33+
/**
34+
* @param ScopeConfigInterface $scopeConfig
35+
* @param JsonHexTag $jsonSerializer
36+
*/
37+
public function __construct(
38+
ScopeConfigInterface $scopeConfig,
39+
JsonHexTag $jsonSerializer
40+
) {
41+
parent::__construct();
42+
43+
$this->scopeConfig = $scopeConfig;
44+
$this->jsonSerializer = $jsonSerializer;
45+
}
46+
47+
/**
48+
* Checks if categories path is used for product URLs.
49+
*
50+
* @return bool
51+
*/
52+
public function isCategoryUsedInProductUrl(): bool
53+
{
54+
return $this->scopeConfig->isSetFlag(
55+
self::XML_PATH_PRODUCT_USE_CATEGORIES,
56+
ScopeInterface::SCOPE_STORE
57+
);
58+
}
59+
60+
/**
61+
* Public getter for the JSON serializer.
62+
*
63+
* @return JsonHexTag
64+
*/
65+
public function getJsonSerializer(): JsonHexTag
66+
{
67+
return $this->jsonSerializer;
68+
}
69+
70+
/**
71+
* Returns an array of SEO configuration options for the navigation menu.
72+
*
73+
* @return array
74+
*/
75+
public function getSeoConfigOptions(): array
76+
{
77+
return [
78+
'menu' => [
79+
'useCategoryPathInUrl' => (int)$this->isCategoryUsedInProductUrl()
80+
]
81+
];
82+
}
83+
}

app/code/Magento/Catalog/ViewModel/TopMenu.php

Lines changed: 0 additions & 125 deletions
This file was deleted.

app/code/Magento/Catalog/view/frontend/layout/default.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,12 @@
6666
<block class="Magento\Framework\View\Element\Js\Components" name="head.components" as="components" template="Magento_Catalog::js/components.phtml"/>
6767
</referenceContainer>
6868
<block class="Magento\Framework\View\Element\Template" name="head.additional" as="head.additional" template="Magento_Theme::html/container.phtml"/>
69+
<referenceContainer name="page.top">
70+
<referenceBlock name="catalog.topnav" template="Magento_Catalog::html/topmenu.phtml">
71+
<arguments>
72+
<argument name="viewModel" xsi:type="object">Magento\Catalog\ViewModel\SeoConfigTopMenu</argument>
73+
</arguments>
74+
</referenceBlock>
75+
</referenceContainer>
6976
</body>
7077
</page>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var $block \Magento\Theme\Block\Html\Topmenu */
8+
/** @var $viewModel \Magento\Catalog\ViewModel\SeoConfigTopMenu */
9+
$viewModel = $block->getData('viewModel');
10+
$columnsLimit = $block->getColumnsLimit() ?: 0;
11+
$menuHtml = $block->getHtml('level-top', 'submenu', $columnsLimit);
12+
$jsonSerializer = $viewModel->getJsonSerializer();
13+
14+
$widgetOptions = [
15+
'menu' => array_merge(
16+
$viewModel->getSeoConfigOptions()['menu'] ?? [],
17+
[
18+
'responsive' => true,
19+
'expanded' => true,
20+
'position' => [
21+
'my' => 'left top',
22+
'at' => 'left bottom'
23+
]
24+
]
25+
)
26+
];
27+
$widgetOptionsJson = $jsonSerializer->serialize($widgetOptions);
28+
?>
29+
30+
<nav class="navigation" data-action="navigation">
31+
<ul data-mage-init='<?= /* @noEscape */ $widgetOptionsJson ?>'>
32+
<?= /* @noEscape */ $menuHtml ?>
33+
<?= $block->getChildHtml() ?>
34+
</ul>
35+
</nav>

app/code/Magento/Theme/view/frontend/layout/default.xml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@
7373
<arguments>
7474
<argument name="title" translate="true" xsi:type="string">Menu</argument>
7575
</arguments>
76-
<block class="Magento\Theme\Block\Html\Topmenu" name="catalog.topnav" template="Magento_Theme::html/topmenu.phtml" ttl="3600" before="-">
77-
<arguments>
78-
<argument name="viewModel" xsi:type="object">Magento\Catalog\ViewModel\TopMenu</argument>
79-
</arguments>
80-
</block>
76+
<block class="Magento\Theme\Block\Html\Topmenu" name="catalog.topnav" template="Magento_Theme::html/topmenu.phtml" ttl="3600" before="-"/>
8177
</block>
8278
<block class="Magento\Framework\View\Element\Text" name="store.links" group="navigation-sections">
8379
<arguments>

app/code/Magento/Theme/view/frontend/templates/html/topmenu.phtml

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,19 @@
44
* See COPYING.txt for license details.
55
*/
66

7-
/** @var $block \Magento\Theme\Block\Html\Topmenu */
8-
/** @var $viewModel \Magento\Catalog\ViewModel\TopMenu */
9-
$viewModel = $block->getData('viewModel');
10-
$columnsLimit = $block->getColumnsLimit() ?: 0;
11-
$menuHtml = $block->getHtml('level-top', 'submenu', $columnsLimit);
12-
$jsonSerializer = $viewModel->getJsonSerializer();
7+
/**
8+
* Top menu for store
9+
*
10+
* @var $block \Magento\Theme\Block\Html\Topmenu
11+
*/
1312

14-
$widget = $jsonSerializer->unserialize($viewModel->getJsonConfigurationHtmlEscaped());
15-
$widgetOptions = [
16-
'menu' => array_merge(
17-
$widget['menu'] ?? [],
18-
[
19-
'responsive' => true,
20-
'expanded' => true,
21-
'position' => [
22-
'my' => 'left top',
23-
'at' => 'left bottom'
24-
]
25-
]
26-
)
27-
];
28-
$widgetOptionsJson = $jsonSerializer->serialize($widgetOptions);
13+
$columnsLimit = $block->getColumnsLimit() ?: 0;
14+
$_menuHtml = $block->getHtml('level-top', 'submenu', $columnsLimit)
2915
?>
3016

3117
<nav class="navigation" data-action="navigation">
32-
<ul data-mage-init='<?= /* @noEscape */ $widgetOptionsJson ?>'>
33-
<?= /* @noEscape */ $menuHtml ?>
18+
<ul data-mage-init='{"menu":{"responsive":true, "expanded":true, "position":{"my":"left top","at":"left bottom"}}}'>
19+
<?= /* @noEscape */ $_menuHtml?>
3420
<?= $block->getChildHtml() ?>
3521
</ul>
3622
</nav>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Block\Html;
7+
8+
use Magento\Catalog\ViewModel\SeoConfigTopMenu as TopMenuViewModel;
9+
use Magento\Framework\View\LayoutInterface;
10+
use Magento\TestFramework\Helper\Bootstrap;
11+
use Magento\Theme\Block\Html\Topmenu;
12+
13+
class TopmenuTest extends \PHPUnit\Framework\TestCase
14+
{
15+
/** @var Topmenu */
16+
private $block;
17+
18+
protected function setUp(): void
19+
{
20+
$this->block = Bootstrap::getObjectManager()
21+
->get(LayoutInterface::class)
22+
->createBlock(Topmenu::class);
23+
}
24+
25+
/**
26+
* Checks top menu template gets correct widget configuration.
27+
*
28+
* @magentoAppArea frontend
29+
*/
30+
public function testGetHtml()
31+
{
32+
$this->block->setTemplate('Magento_Catalog::html/topmenu.phtml');
33+
$topMenuViewModel = Bootstrap::getObjectManager()->get(TopMenuViewModel ::class);
34+
$this->block->setData('viewModel', $topMenuViewModel);
35+
$html = $this->block->toHtml();
36+
$this->assertStringContainsString(
37+
'"useCategoryPathInUrl":0',
38+
$html,
39+
"The HTML does not contain the expected JSON fragment."
40+
);
41+
}
42+
}

0 commit comments

Comments
 (0)