Skip to content

Commit 9871045

Browse files
committed
Fix #9 - Fix false-positive where any path of the length of the configured value would match
1 parent de78c7f commit 9871045

File tree

2 files changed

+32
-26
lines changed

2 files changed

+32
-26
lines changed

App/Request/PathInfoProcessor.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,25 @@ public function process(RequestInterface $request, $pathInfo): string
3636
return $this->subject->process($request, $pathInfo);
3737
}
3838

39-
$storeCode = $this->storePathInfoValidator->getValidStoreCode($request, $pathInfo);
39+
$storeCode = $this->storePathInfoValidator->getValidStoreCode($request);
4040
if ($storeCode !== null) {
4141
try {
42-
$path = $this->pathResolver->resolve($this->storeRepository->getActiveStoreByCode($storeCode));
42+
$storePath = $this->pathResolver->resolve($this->storeRepository->getActiveStoreByCode($storeCode));
4343
} catch (LocalizedException) {
4444
return $pathInfo;
4545
}
46-
if (!$request->isDirectAccessFrontendName($path)) {
47-
$pathInfo = substr($pathInfo, strlen($path) + (int)str_starts_with($pathInfo, '/')) ?: '/';
46+
if (!$request->isDirectAccessFrontendName($storePath)) {
47+
// Armored test to prevent cases where the path wouldn't start by a "/" when it's expected.
48+
if (str_starts_with($pathInfo, '/')) {
49+
$storePath = '/' . $storePath;
50+
}
51+
// Prevent to trim a part where the store path could be included.
52+
// E.g: We assume we have the store path "fr", we don't want to trim the "fr" of "/franchise".
53+
if (str_starts_with($pathInfo . '/', $storePath . '/')) {
54+
$pathInfo = substr($pathInfo, strlen($storePath)) ?: '/';
55+
}
4856
} else {
49-
//no route in case we're trying to access a store that has the same code as a direct access
57+
// No route in case we're trying to access a store that has the same code as a direct access.
5058
$request->setActionName(Base::NO_ROUTE);
5159
}
5260
}

Plugin/App/Request/StorePathInfoValidator.php

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
namespace Opengento\StorePathUrl\Plugin\App\Request;
99

1010
use Magento\Framework\App\Request\Http;
11-
use Magento\Framework\Exception\LocalizedException;
1211
use Magento\Framework\Exception\NoSuchEntityException;
1312
use Magento\Framework\UrlInterface;
1413
use Magento\Store\Api\StoreRepositoryInterface;
@@ -23,6 +22,8 @@
2322

2423
class StorePathInfoValidator
2524
{
25+
// This hack is necessary to prevent infinite loop because of https://github.com/opengento/magento2-store-path-url/issues/3
26+
// The fix is shipped in the version 2.4.9 of Magento: https://github.com/magento/magento2/pull/38717
2627
private int $stack = 0;
2728

2829
public function __construct(
@@ -32,47 +33,42 @@ public function __construct(
3233

3334
public function beforeGetValidStoreCode(Subject $subject, Http $request, string $pathInfo = ''): array
3435
{
35-
if (++$this->stack === 1 && $this->config->isStoreInPath() && $this->config->isBaseUrlResolverEnabled()) {
36-
$storeCode = $this->resolveStoreCode($request, $pathInfo);
37-
$pathInfo = $storeCode === '' ? $pathInfo : $storeCode;
36+
// If $pathInfo is empty, we are resolving the current scope ID.
37+
// It could also be the path info processor which tries to trim the store path from the url.
38+
if (++$this->stack === 1 && $pathInfo === '' && $this->config->isStoreInPath() && $this->config->isBaseUrlResolverEnabled()) {
39+
$pathInfo = $this->resolveStoreCode($request);
3840
}
3941

4042
return [$request, $pathInfo];
4143
}
42-
44+
4345
public function afterGetValidStoreCode(Subject $subject, ?string $store, Http $request, string $path = ''): ?string
4446
{
45-
if ($this->stack === 1 && !$this->config->isStoreInPath() && $this->config->isBaseUrlResolverEnabled()) {
46-
try {
47-
$store = $this->storeRepository->getActiveStoreByCode(
48-
$this->resolveStoreCode($request, $path)
49-
)->getCode();
50-
} catch (LocalizedException) {
51-
$store = null;
52-
}
53-
}
5447
$this->stack--;
5548

5649
return $store;
5750
}
5851

59-
private function resolveStoreCode(Http $request, string $pathInfo): string
52+
private function resolveStoreCode(Http $request): string
6053
{
6154
$uri = strtok($request->getUriString(), '?') . '/';
6255
if ($uri !== false) {
63-
$pathInfo = $pathInfo ?: parse_url($uri, PHP_URL_PATH);
56+
$pathInfo = parse_url($uri, PHP_URL_PATH);
6457
if ($pathInfo === false) {
6558
return '';
6659
}
67-
$pathInfo = $this->resolveByLinkUrl($uri) ?: $this->resolveByWebUrl($uri);
60+
// The uri has a valid format, we can look for the matching store base url.
61+
$pathInfo = $this->resolveByLinkUrl($uri);
62+
// If the store cannot be resolved, with look for the closest lookalike store.
63+
return $pathInfo !== false ? $pathInfo : $this->resolveByWebUrl($uri);
6864
}
6965

70-
return $pathInfo;
66+
return '';
7167
}
7268

73-
private function resolveByLinkUrl(string $uri): string
69+
private function resolveByLinkUrl(string $uri): bool|string
7470
{
75-
$storeCode = '';
71+
$storeCode = false;
7672
/** @var Store $store */
7773
foreach ($this->storeRepository->getList() as $store) {
7874
if ($store->getId()) {
@@ -100,7 +96,9 @@ private function resolveByWebUrl(string $uri): string
10096
if ($store->getId() && str_starts_with($uri, $store->getBaseUrl(UrlInterface::URL_TYPE_WEB))) {
10197
try {
10298
$score = $this->calculatePreferenceScore($store);
103-
$storeMatch ??= $store->getCode();
99+
if ($storeMatch === null) {
100+
$storeMatch = $store->getCode();
101+
}
104102
if ($highestScore < $score) {
105103
$highestScore = $score;
106104
$storeMatch = $store->getCode();

0 commit comments

Comments
 (0)