Skip to content

Add Store Code to Urls should be Global #40065

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: 2.4-develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion app/code/Magento/Catalog/Test/Unit/Block/Widget/LinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,17 @@ public function testStoreCodeShouldBeIncludedInURLOnlyIfItIsConfiguredSo(
[
[Store::XML_PATH_USE_REWRITES, ReinitableConfigInterface::SCOPE_TYPE_DEFAULT, null, true],
[Store::XML_PATH_UNSECURE_BASE_LINK_URL, ScopeConfigInterface::SCOPE_TYPE_DEFAULT, null, ''],
]
);
$config->expects($this->any())
->method('isSetFlag')
->willReturnMap(
[
[
Store::XML_PATH_STORE_IN_URL,
ReinitableConfigInterface::SCOPE_TYPE_DEFAULT,
null, $includeStoreCode
null,
$includeStoreCode
]
]
);
Expand Down
18 changes: 6 additions & 12 deletions app/code/Magento/Store/App/Request/StorePathInfoValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,16 @@ public function __construct(
*/
public function getValidStoreCode(Http $request, string $pathInfo = '') : ?string
{
$useStoreCodeInUrl = (bool) $this->config->getValue(Store::XML_PATH_STORE_IN_URL);
if (!$useStoreCodeInUrl) {
if (!$this->config->isSetFlag(Store::XML_PATH_STORE_IN_URL)) {
return null;
}

if (empty($pathInfo)) {
if ($pathInfo === '') {
$pathInfo = $this->pathInfo->getPathInfo($request->getRequestUri(), $request->getBaseUrl());
}
$storeCode = $this->getStoreCode($pathInfo);

if (empty($storeCode) || $storeCode === Store::ADMIN_CODE || !$this->storeCodeValidator->isValid($storeCode)) {
if ($storeCode === '' || $storeCode === Store::ADMIN_CODE || !$this->storeCodeValidator->isValid($storeCode)) {
return null;
}

Expand All @@ -98,14 +97,9 @@ public function getValidStoreCode(Http $request, string $pathInfo = '') : ?strin
try {
$this->storeRepository->getActiveStoreByCode($storeCode);

$this->validatedStoreCodes[$storeCode] = $storeCode;
return $storeCode;
} catch (NoSuchEntityException $e) {
$this->validatedStoreCodes[$storeCode] = null;
return null;
} catch (StoreIsInactiveException $e) {
$this->validatedStoreCodes[$storeCode] = null;
return null;
return $this->validatedStoreCodes[$storeCode] = $storeCode;
} catch (NoSuchEntityException|StoreIsInactiveException) {
return $this->validatedStoreCodes[$storeCode] = null;
}
}

Expand Down
4 changes: 2 additions & 2 deletions app/code/Magento/Store/Model/Store.php
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,8 @@ protected function _updatePathUseStoreView($url)
public function isUseStoreInUrl()
{
return !($this->hasDisableStoreInUrl() && $this->getDisableStoreInUrl())
&& !$this->getConfig(StoreManager::XML_PATH_SINGLE_STORE_MODE_ENABLED)
&& $this->getConfig(self::XML_PATH_STORE_IN_URL);
&& !$this->_config->isSetFlag(StoreManager::XML_PATH_SINGLE_STORE_MODE_ENABLED)
&& $this->_config->isSetFlag(self::XML_PATH_STORE_IN_URL);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function testGetValidStoreCodeWithoutStoreInUrl(): void
->willReturn(true);

$this->configMock->expects($this->once())
->method('getValue')
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(false);
$this->storeRepositoryMock->expects($this->never())
Expand All @@ -95,7 +95,7 @@ public function testGetValidStoreCodeWithoutPathInfo(): void
$storeCode = 'store1';

$this->configMock->expects($this->once())
->method('getValue')
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);
$this->pathInfoMock->expects($this->once())
Expand All @@ -118,7 +118,7 @@ public function testGetValidStoreCodeWithoutPathInfo(): void
public function testGetValidStoreCodeWithEmptyPathInfo(): void
{
$this->configMock->expects($this->once())
->method('getValue')
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);
$this->pathInfoMock->expects($this->once())
Expand All @@ -139,7 +139,7 @@ public function testGetValidStoreCodeWithEmptyPathInfo(): void
*/
public function testGetValidStoreCodeThrowsException(\Throwable $exception): void
{
$this->configMock->method('getValue')
$this->configMock->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);
$this->storeCodeValidatorMock->method('isValid')
Expand Down Expand Up @@ -169,7 +169,7 @@ public static function getValidStoreCodeExceptionDataProvider(): array
*/
public function testGetValidStoreCode(string $pathInfo, bool $isStoreCodeValid, ?string $expectedResult): void
{
$this->configMock->method('getValue')
$this->configMock->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);
$this->pathInfoMock->method('getPathInfo')
Expand All @@ -195,7 +195,7 @@ public function testGetValidStoreCodeResultIsCached(
bool $isStoreCodeValid,
?string $expectedResult
): void {
$this->configMock->method('getValue')
$this->configMock->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);
$this->pathInfoMock->method('getPathInfo')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2015 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

Expand Down Expand Up @@ -54,10 +54,7 @@ protected function setUp(): void
$this->storeMock->expects($this->any())->method('getCode')->willReturn('custom_store');

$this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class);
$this->storeManagerMock
->expects($this->once())
->method('getStore')
->willReturn($this->storeMock);
$this->storeManagerMock->method('getStore')->willReturn($this->storeMock);

$this->queryParamsResolverMock = $this->getMockForAbstractClass(QueryParamsResolverInterface::class);
$this->model = new RouteParamsResolver(
Expand All @@ -74,12 +71,8 @@ public function testBeforeSetRouteParamsScopeInParams()

$this->scopeConfigMock
->expects($this->once())
->method('getValue')
->with(
Store::XML_PATH_STORE_IN_URL,
ScopeInterface::SCOPE_STORE,
$storeCode
)
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(false);
$this->storeManagerMock->expects($this->any())->method('hasSingleStore')->willReturn(false);

Expand All @@ -106,30 +99,23 @@ public function testBeforeSetRouteParamsScopeUseStoreInUrl()

$this->scopeConfigMock
->expects($this->once())
->method('getValue')
->with(
Store::XML_PATH_STORE_IN_URL,
ScopeInterface::SCOPE_STORE,
$storeCode
)
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);

$this->storeManagerMock->expects($this->any())->method('hasSingleStore')->willReturn(false);
$this->storeManagerMock->expects($this->never())->method('hasSingleStore');

/** @var MockObject $routeParamsResolverMock */
$routeParamsResolverMock = $this->getMockBuilder(\Magento\Framework\Url\RouteParamsResolver::class)
->addMethods(['setScope', 'getScope'])
->disableOriginalConstructor()
->getMock();
$routeParamsResolverMock->expects($this->once())->method('setScope')->with($storeCode);
$routeParamsResolverMock->expects($this->once())->method('getScope')->willReturn($storeCode);
$routeParamsResolverMock->expects($this->never())->method('getScope');

$this->queryParamsResolverMock->expects($this->never())->method('setQueryParam')->with('___store', $storeCode);

$this->model->beforeSetRouteParams(
$routeParamsResolverMock,
$data
);
$this->model->beforeSetRouteParams($routeParamsResolverMock, $data);
}

public function testBeforeSetRouteParamsSingleStore()
Expand All @@ -139,22 +125,18 @@ public function testBeforeSetRouteParamsSingleStore()

$this->scopeConfigMock
->expects($this->once())
->method('getValue')
->with(
Store::XML_PATH_STORE_IN_URL,
ScopeInterface::SCOPE_STORE,
$storeCode
)
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(false);
$this->storeManagerMock->expects($this->any())->method('hasSingleStore')->willReturn(true);
$this->storeManagerMock->expects($this->once())->method('hasSingleStore')->willReturn(true);

/** @var MockObject $routeParamsResolverMock */
$routeParamsResolverMock = $this->getMockBuilder(\Magento\Framework\Url\RouteParamsResolver::class)
->addMethods(['setScope', 'getScope'])
->disableOriginalConstructor()
->getMock();
$routeParamsResolverMock->expects($this->once())->method('setScope')->with($storeCode);
$routeParamsResolverMock->expects($this->once())->method('getScope')->willReturn($storeCode);
$routeParamsResolverMock->expects($this->never())->method('getScope');

$this->queryParamsResolverMock->expects($this->never())->method('setQueryParam');

Expand All @@ -171,23 +153,19 @@ public function testBeforeSetRouteParamsNoScopeInParams()

$this->scopeConfigMock
->expects($this->once())
->method('getValue')
->with(
Store::XML_PATH_STORE_IN_URL,
ScopeInterface::SCOPE_STORE,
$storeCode
)
->method('isSetFlag')
->with(Store::XML_PATH_STORE_IN_URL)
->willReturn(true);

$this->storeManagerMock->expects($this->any())->method('hasSingleStore')->willReturn(false);
$this->storeManagerMock->expects($this->never())->method('hasSingleStore');

/** @var MockObject $routeParamsResolverMock */
$routeParamsResolverMock = $this->getMockBuilder(\Magento\Framework\Url\RouteParamsResolver::class)
->addMethods(['setScope', 'getScope'])
->disableOriginalConstructor()
->getMock();
$routeParamsResolverMock->expects($this->never())->method('setScope');
$routeParamsResolverMock->expects($this->once())->method('getScope')->willReturn(false);
$routeParamsResolverMock->expects($this->never())->method('getScope');

$this->queryParamsResolverMock->expects($this->never())->method('setQueryParam')->with('___store', $storeCode);

Expand Down
70 changes: 24 additions & 46 deletions app/code/Magento/Store/Url/Plugin/RouteParamsResolver.php
Original file line number Diff line number Diff line change
@@ -1,49 +1,37 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2015 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

namespace Magento\Store\Url\Plugin;

use \Magento\Store\Model\Store;
use \Magento\Store\Api\Data\StoreInterface;
use \Magento\Store\Model\ScopeInterface as StoreScopeInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Url\RouteParamsResolver as UrlRouteParamsResolver;
use Magento\Framework\Url\QueryParamsResolverInterface;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\ScopeInterface as StoreScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Store\Model\Store;

/**
* Plugin for \Magento\Framework\Url\RouteParamsResolver
*/
class RouteParamsResolver
{
/**
* @var \Magento\Framework\App\Config\ScopeConfigInterface
*/
protected $scopeConfig;

/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;

/**
* @var \Magento\Framework\Url\QueryParamsResolverInterface
*/
protected $queryParamsResolver;

/**
* Initialize dependencies.
*
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver
* @param ScopeConfigInterface $scopeConfig
* @param StoreManagerInterface $storeManager
* @param QueryParamsResolverInterface $queryParamsResolver
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Url\QueryParamsResolverInterface $queryParamsResolver
protected ScopeConfigInterface $scopeConfig,
protected StoreManagerInterface $storeManager,
protected QueryParamsResolverInterface $queryParamsResolver
) {
$this->scopeConfig = $scopeConfig;
$this->storeManager = $storeManager;
$this->queryParamsResolver = $queryParamsResolver;
}

/**
Expand All @@ -56,29 +44,19 @@ public function __construct(
*
* @return array
*/
public function beforeSetRouteParams(
\Magento\Framework\Url\RouteParamsResolver $subject,
array $data,
$unsetOldParams = true
) {
public function beforeSetRouteParams(UrlRouteParamsResolver $subject, array $data, $unsetOldParams = true)
{
if (isset($data['_scope'])) {
$subject->setScope($data['_scope']);
unset($data['_scope']);
}
if (isset($data['_scope_to_url']) && (bool)$data['_scope_to_url'] === true) {
/** @var StoreInterface $currentScope */
$currentScope = $subject->getScope();
$storeCode = $currentScope && $currentScope instanceof StoreInterface ?
$currentScope->getCode() :
$this->storeManager->getStore()->getCode();

$useStoreInUrl = $this->scopeConfig->getValue(
Store::XML_PATH_STORE_IN_URL,
StoreScopeInterface::SCOPE_STORE,
$storeCode
);

$useStoreInUrl = $this->scopeConfig->isSetFlag(Store::XML_PATH_STORE_IN_URL);
if (!$useStoreInUrl && !$this->storeManager->hasSingleStore()) {
$currentScope = $subject->getScope();
$storeCode = $currentScope instanceof StoreInterface
? $currentScope->getCode()
: $this->storeManager->getStore()->getCode();
$this->queryParamsResolver->setQueryParam('___store', $storeCode);
}
}
Expand Down
Loading