Skip to content

Commit 7cdf8bd

Browse files
committed
MC-40538: When entering example.com/0 into browser the homepage is shown (example.com)
1 parent b6eecf2 commit 7cdf8bd

File tree

7 files changed

+210
-86
lines changed

7 files changed

+210
-86
lines changed

app/code/Magento/Store/App/Request/PathInfoProcessor.php

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,56 +7,48 @@
77

88
namespace Magento\Store\App\Request;
99

10+
use Magento\Framework\App\Request\PathInfoProcessorInterface;
11+
use Magento\Framework\App\RequestInterface;
12+
1013
/**
1114
* Processes the path and looks for the store in the url and removes it and modifies the path accordingly.
1215
*/
13-
class PathInfoProcessor implements \Magento\Framework\App\Request\PathInfoProcessorInterface
16+
class PathInfoProcessor implements PathInfoProcessorInterface
1417
{
1518
/**
1619
* @var StorePathInfoValidator
1720
*/
1821
private $storePathInfoValidator;
1922

2023
/**
21-
* @var \Magento\Framework\App\Config\ReinitableConfigInterface
22-
*/
23-
private $config;
24-
25-
/**
26-
* @param \Magento\Store\App\Request\StorePathInfoValidator $storePathInfoValidator
27-
* @param \Magento\Framework\App\Config\ReinitableConfigInterface $config
24+
* @param StorePathInfoValidator $storePathInfoValidator
2825
*/
29-
public function __construct(
30-
\Magento\Store\App\Request\StorePathInfoValidator $storePathInfoValidator,
31-
\Magento\Framework\App\Config\ReinitableConfigInterface $config
32-
) {
26+
public function __construct(StorePathInfoValidator $storePathInfoValidator)
27+
{
3328
$this->storePathInfoValidator = $storePathInfoValidator;
34-
$this->config = $config;
3529
}
3630

3731
/**
3832
* Process path info and remove store from pathInfo.
3933
*
4034
* This method also sets request to no route if store is not valid and store is present in url config is enabled
4135
*
42-
* @param \Magento\Framework\App\RequestInterface $request
36+
* @param RequestInterface $request
4337
* @param string $pathInfo
4438
* @return string
4539
*/
46-
public function process(\Magento\Framework\App\RequestInterface $request, $pathInfo) : string
40+
public function process(RequestInterface $request, $pathInfo) : string
4741
{
48-
//can store code be used in url
49-
if ((bool)$this->config->getValue(\Magento\Store\Model\Store::XML_PATH_STORE_IN_URL)) {
50-
$storeCode = $this->storePathInfoValidator->getValidStoreCode($request, $pathInfo);
51-
if (!empty($storeCode)) {
52-
if (!$request->isDirectAccessFrontendName($storeCode)) {
53-
$pathInfo = $this->trimStoreCodeFromPathInfo($pathInfo, $storeCode);
54-
} else {
55-
//no route in case we're trying to access a store that has the same code as a direct access
56-
$request->setActionName(\Magento\Framework\App\Router\Base::NO_ROUTE);
57-
}
42+
$storeCode = $this->storePathInfoValidator->getValidStoreCode($request, $pathInfo);
43+
if (!empty($storeCode)) {
44+
if (!$request->isDirectAccessFrontendName($storeCode)) {
45+
$pathInfo = $this->trimStoreCodeFromPathInfo($pathInfo, $storeCode);
46+
} else {
47+
//no route in case we're trying to access a store that has the same code as a direct access
48+
$request->setActionName(\Magento\Framework\App\Router\Base::NO_ROUTE);
5849
}
5950
}
51+
6052
return $pathInfo;
6153
}
6254

@@ -67,7 +59,7 @@ public function process(\Magento\Framework\App\RequestInterface $request, $pathI
6759
* @param string $storeCode
6860
* @return string
6961
*/
70-
private function trimStoreCodeFromPathInfo(string $pathInfo, string $storeCode) : ?string
62+
private function trimStoreCodeFromPathInfo(string $pathInfo, string $storeCode) : string
7163
{
7264
if (substr($pathInfo, 0, strlen('/' . $storeCode)) == '/'. $storeCode) {
7365
$pathInfo = substr($pathInfo, strlen($storeCode)+1);

app/code/Magento/Store/App/Request/StorePathInfoValidator.php

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77

88
namespace Magento\Store\App\Request;
99

10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\App\Request\Http;
12+
use Magento\Framework\App\Request\PathInfo;
1013
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Store\Api\StoreRepositoryInterface;
1115
use Magento\Store\Model\Store;
16+
use Magento\Store\Model\StoreIsInactiveException;
1217

1318
/**
1419
* Gets the store from the path if valid
@@ -18,29 +23,29 @@ class StorePathInfoValidator
1823
/**
1924
* Store Config
2025
*
21-
* @var \Magento\Framework\App\Config\ReinitableConfigInterface
26+
* @var ScopeConfigInterface
2227
*/
2328
private $config;
2429

2530
/**
26-
* @var \Magento\Store\Api\StoreRepositoryInterface
31+
* @var StoreRepositoryInterface
2732
*/
2833
private $storeRepository;
2934

3035
/**
31-
* @var \Magento\Framework\App\Request\PathInfo
36+
* @var PathInfo
3237
*/
3338
private $pathInfo;
3439

3540
/**
36-
* @param \Magento\Framework\App\Config\ReinitableConfigInterface $config
37-
* @param \Magento\Store\Api\StoreRepositoryInterface $storeRepository
38-
* @param \Magento\Framework\App\Request\PathInfo $pathInfo
41+
* @param ScopeConfigInterface $config
42+
* @param StoreRepositoryInterface $storeRepository
43+
* @param PathInfo $pathInfo
3944
*/
4045
public function __construct(
41-
\Magento\Framework\App\Config\ReinitableConfigInterface $config,
42-
\Magento\Store\Api\StoreRepositoryInterface $storeRepository,
43-
\Magento\Framework\App\Request\PathInfo $pathInfo
46+
ScopeConfigInterface $config,
47+
StoreRepositoryInterface $storeRepository,
48+
PathInfo $pathInfo
4449
) {
4550
$this->config = $config;
4651
$this->storeRepository = $storeRepository;
@@ -50,42 +55,34 @@ public function __construct(
5055
/**
5156
* Get store code from path info validate if config value. If path info is empty the try to calculate from request.
5257
*
53-
* @param \Magento\Framework\App\Request\Http $request
58+
* @param Http $request
5459
* @param string $pathInfo
5560
* @return string|null
5661
*/
57-
public function getValidStoreCode(
58-
\Magento\Framework\App\Request\Http $request,
59-
string $pathInfo = ''
60-
) : ?string {
62+
public function getValidStoreCode(Http $request, string $pathInfo = '') : ?string
63+
{
64+
$useStoreCodeInUrl = (bool) $this->config->getValue(Store::XML_PATH_STORE_IN_URL);
65+
if (!$useStoreCodeInUrl) {
66+
return null;
67+
}
68+
6169
if (empty($pathInfo)) {
62-
$pathInfo = $this->pathInfo->getPathInfo(
63-
$request->getRequestUri(),
64-
$request->getBaseUrl()
65-
);
70+
$pathInfo = $this->pathInfo->getPathInfo($request->getRequestUri(), $request->getBaseUrl());
6671
}
6772
$storeCode = $this->getStoreCode($pathInfo);
68-
if (!empty($storeCode)
69-
&& $storeCode != Store::ADMIN_CODE
70-
&& (bool)$this->config->getValue(\Magento\Store\Model\Store::XML_PATH_STORE_IN_URL)
71-
) {
72-
try {
73-
$this->storeRepository->getActiveStoreByCode($storeCode);
73+
if (empty($storeCode) || $storeCode === Store::ADMIN_CODE) {
74+
return null;
75+
}
76+
77+
try {
78+
$this->storeRepository->getActiveStoreByCode($storeCode);
7479

75-
if ((bool)$this->config->getValue(
76-
\Magento\Store\Model\Store::XML_PATH_STORE_IN_URL,
77-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
78-
$storeCode
79-
)) {
80-
return $storeCode;
81-
}
82-
} catch (NoSuchEntityException $e) {
83-
//return null;
84-
} catch (\Magento\Store\Model\StoreIsInactiveException $e) {
85-
//return null;
86-
}
80+
return $storeCode;
81+
} catch (NoSuchEntityException $e) {
82+
return null;
83+
} catch (StoreIsInactiveException $e) {
84+
return null;
8785
}
88-
return null;
8986
}
9087

9188
/**

app/code/Magento/Store/Model/Store.php

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ class Store extends AbstractExtensibleModel implements
332332
*/
333333
private $pillPut;
334334

335+
/**
336+
* @var Validation\StoreValidator
337+
*/
338+
private $modelValidator;
339+
335340
/**
336341
* @param \Magento\Framework\Model\Context $context
337342
* @param \Magento\Framework\Registry $registry
@@ -359,7 +364,7 @@ class Store extends AbstractExtensibleModel implements
359364
* @param array $data optional generic object data
360365
* @param \Magento\Framework\Event\ManagerInterface|null $eventManager
361366
* @param \Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface|null $pillPut
362-
*
367+
* @param \Magento\Store\Model\Validation\StoreValidator|null $modelValidator
363368
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
364369
*/
365370
public function __construct(
@@ -388,7 +393,8 @@ public function __construct(
388393
$isCustomEntryPoint = false,
389394
array $data = [],
390395
\Magento\Framework\Event\ManagerInterface $eventManager = null,
391-
\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null
396+
\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface $pillPut = null,
397+
?\Magento\Store\Model\Validation\StoreValidator $modelValidator = null
392398
) {
393399
$this->_coreFileStorageDatabase = $coreFileStorageDatabase;
394400
$this->_config = $config;
@@ -411,6 +417,8 @@ public function __construct(
411417
->get(\Magento\Framework\Event\ManagerInterface::class);
412418
$this->pillPut = $pillPut ?: \Magento\Framework\App\ObjectManager::getInstance()
413419
->get(\Magento\Framework\MessageQueue\PoisonPill\PoisonPillPutInterface::class);
420+
$this->modelValidator = $modelValidator ?? \Magento\Framework\App\ObjectManager::getInstance()
421+
->get(\Magento\Store\Model\Validation\StoreValidator::class);
414422
parent::__construct(
415423
$context,
416424
$registry,
@@ -472,30 +480,11 @@ protected function _getSession()
472480
}
473481

474482
/**
475-
* Validation rules for store
476-
*
477-
* @return \Zend_Validate_Interface|null
478-
* @throws \Zend_Validate_Exception
483+
* @inheritDoc
479484
*/
480485
protected function _getValidationRulesBeforeSave()
481486
{
482-
$validator = new \Magento\Framework\Validator\DataObject();
483-
484-
$storeLabelRule = new \Zend_Validate_NotEmpty();
485-
$storeLabelRule->setMessage(__('Name is required'), \Zend_Validate_NotEmpty::IS_EMPTY);
486-
$validator->addRule($storeLabelRule, 'name');
487-
488-
$storeCodeRule = new \Zend_Validate_Regex('/^[a-z]+[a-z0-9_]*$/i');
489-
$storeCodeRule->setMessage(
490-
__(
491-
'The store code may contain only letters (a-z), numbers (0-9) or underscore (_),'
492-
. ' and the first character must be a letter.'
493-
),
494-
\Zend_Validate_Regex::NOT_MATCH
495-
);
496-
$validator->addRule($storeCodeRule, 'code');
497-
498-
return $validator;
487+
return $this->modelValidator;
499488
}
500489

501490
/**
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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\Store\Model\Validation;
9+
10+
use Magento\Framework\Validator\AbstractValidator;
11+
use Magento\Framework\Validator\RegexFactory;
12+
13+
/**
14+
* Validator for store code.
15+
*/
16+
class StoreCodeValidator extends AbstractValidator
17+
{
18+
/**
19+
* @var RegexFactory
20+
*/
21+
private $regexValidatorFactory;
22+
23+
/**
24+
* @param RegexFactory $regexValidatorFactory
25+
*/
26+
public function __construct(RegexFactory $regexValidatorFactory)
27+
{
28+
$this->regexValidatorFactory = $regexValidatorFactory;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function isValid($value)
35+
{
36+
$validator = $this->regexValidatorFactory->create(['pattern' => '/^[a-z]+[a-z0-9_]*$/i']);
37+
$validator->setMessage(
38+
__(
39+
'The store code may contain only letters (a-z), numbers (0-9) or underscore (_),'
40+
. ' and the first character must be a letter.'
41+
),
42+
\Zend_Validate_Regex::NOT_MATCH
43+
);
44+
45+
return $validator->isValid($value);
46+
}
47+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\Store\Model\Validation;
9+
10+
use Magento\Framework\Validator\AbstractValidator;
11+
use Magento\Framework\Validator\NotEmptyFactory;
12+
13+
/**
14+
* Validator for store name.
15+
*/
16+
class StoreNameValidator extends AbstractValidator
17+
{
18+
/**
19+
* @var NotEmptyFactory
20+
*/
21+
private $notEmptyValidatorFactory;
22+
23+
/**
24+
* @param NotEmptyFactory $notEmptyValidatorFactory
25+
*/
26+
public function __construct(NotEmptyFactory $notEmptyValidatorFactory)
27+
{
28+
$this->notEmptyValidatorFactory = $notEmptyValidatorFactory;
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
public function isValid($value)
35+
{
36+
$validator = $this->notEmptyValidatorFactory->create();
37+
$validator->setMessage(__('Name is required'), \Zend_Validate_NotEmpty::IS_EMPTY);
38+
39+
return $validator->isValid($value);
40+
}
41+
}

0 commit comments

Comments
 (0)