Skip to content

Commit 4d87ce6

Browse files
committed
Init custom store path url module
0 parents  commit 4d87ce6

File tree

21 files changed

+768
-0
lines changed

21 files changed

+768
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
* See LICENSE bundled with this library for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Opengento\StorePathUrl\Block\Adminhtml\Config\Form\Field\Select;
9+
10+
use Magento\Framework\View\Element\Context;
11+
use Magento\Framework\View\Element\Html\Select;
12+
use Magento\Store\Model\System\Store as StoreSource;
13+
14+
class Store extends Select
15+
{
16+
private StoreSource $storeSource;
17+
18+
public function __construct(
19+
Context $context,
20+
StoreSource $storeSource,
21+
array $data = []
22+
) {
23+
$this->storeSource = $storeSource;
24+
parent::__construct($context, $data);
25+
}
26+
27+
public function setInputName(string $inputName): self
28+
{
29+
return $this->setData('name', $inputName);
30+
}
31+
32+
protected function _toHtml(): string
33+
{
34+
if ($this->getData('multiple')) {
35+
$this->setData('extra_params', 'multiple="multiple"');
36+
$this->setInputName($this->getData('name') . '[]');
37+
}
38+
if (!$this->getOptions()) {
39+
$this->setOptions($this->storeSource->toOptionArray());
40+
}
41+
42+
return parent::_toHtml();
43+
}
44+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
* See LICENSE bundled with this library for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Opengento\StorePathUrl\Block\Adminhtml\Config\Form\Field;
9+
10+
use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray;
11+
use Magento\Framework\DataObject;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Phrase;
14+
use Magento\Framework\View\Element\Html\Select;
15+
use Opengento\StorePathUrl\Block\Adminhtml\Config\Form\Field\Select\Store;
16+
17+
class StorePath extends AbstractFieldArray
18+
{
19+
/**
20+
* @throws LocalizedException
21+
*/
22+
public function getStoreSelectRenderer(): Select
23+
{
24+
if (!$this->hasData('store_select_renderer')) {
25+
$this->setData(
26+
'store_select_renderer',
27+
$this->getLayout()->createBlock(
28+
Store::class,
29+
'',
30+
['data' => ['is_render_to_js_template' => true]]
31+
)
32+
);
33+
}
34+
35+
return $this->getData('store_select_renderer');
36+
}
37+
38+
/**
39+
* @throws LocalizedException
40+
*/
41+
protected function _prepareToRender(): void
42+
{
43+
$this->addColumn(
44+
'store',
45+
[
46+
'label' => new Phrase('Store'),
47+
'class' => 'required-entry',
48+
'renderer' => $this->getStoreSelectRenderer(),
49+
]
50+
);
51+
$this->addColumn('path', ['label' => new Phrase('Path'), 'class' => 'required-entry']);
52+
$this->_addAfter = false;
53+
$this->_addButtonLabel = (new Phrase('Add Store Path'))->render();
54+
}
55+
56+
/**
57+
* @inheritdoc
58+
* @throws LocalizedException
59+
*/
60+
protected function _prepareArrayRow(DataObject $row): void
61+
{
62+
$row->setData(
63+
'option_extra_attrs',
64+
[
65+
'option_' . $this->getStoreSelectRenderer()->calcOptionHash($row->getData('store')) => 'selected="selected"',
66+
]
67+
);
68+
}
69+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) OpenGento
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Model/Config.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Model;
8+
9+
use Magento\Directory\Helper\Data;
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\Serialize\SerializerInterface;
12+
use Magento\Store\Api\Data\StoreInterface;
13+
use Magento\Store\Model\ScopeInterface;
14+
use Magento\Store\Model\Store;
15+
use Opengento\StorePathUrl\Model\Config\PathType;
16+
17+
class Config
18+
{
19+
private const CONFIG_PATH_USE_STORE_PATH = 'web/url/use_store_path';
20+
private const CONFIG_PATH_CUSTOM_PATH_MAPPER = 'web/url/custom_path_mapper';
21+
22+
private ?array $customPathMapper = null;
23+
24+
public function __construct(
25+
private ScopeConfigInterface $scopeConfig,
26+
private SerializerInterface $serializer
27+
) {}
28+
29+
public function isEnabled(): bool
30+
{
31+
return $this->scopeConfig->isSetFlag(Store::XML_PATH_STORE_IN_URL)
32+
&& $this->getStorePathType() !== PathType::StoreCode;
33+
}
34+
35+
public function getStorePathType(): PathType
36+
{
37+
return PathType::from($this->scopeConfig->getValue(self::CONFIG_PATH_USE_STORE_PATH));
38+
}
39+
40+
public function getCountry(StoreInterface $store): string
41+
{
42+
return (string)$this->scopeConfig->getValue(
43+
Data::XML_PATH_DEFAULT_COUNTRY,
44+
ScopeInterface::SCOPE_STORE,
45+
$store->getId()
46+
);
47+
}
48+
49+
public function getLocale(StoreInterface $store): string
50+
{
51+
return (string)$this->scopeConfig->getValue(
52+
Data::XML_PATH_DEFAULT_LOCALE,
53+
ScopeInterface::SCOPE_STORE,
54+
$store->getId()
55+
);
56+
}
57+
58+
public function getCustomPathMapper(): array
59+
{
60+
return $this->customPathMapper ??= $this->resolveCustomPathMapper();
61+
}
62+
63+
private function resolveCustomPathMapper(): array
64+
{
65+
$customPaths = $this->serializer->unserialize(
66+
$this->scopeConfig->getValue(self::CONFIG_PATH_CUSTOM_PATH_MAPPER) ?? '{}'
67+
);
68+
69+
$mapper = [];
70+
foreach ($customPaths as $customPath) {
71+
if (isset($customPath['store'], $customPath['path'])) {
72+
$mapper[(int)$customPath['store']] = (string)$customPath['path'];
73+
}
74+
}
75+
76+
return $mapper;
77+
}
78+
}

Model/Config/PathType.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Model\Config;
8+
9+
use Magento\Framework\Phrase;
10+
11+
enum PathType: string
12+
{
13+
private const PHRASES = [
14+
self::StoreCode->value => 'Store Code',
15+
self::CountryCode->value => 'Country Code',
16+
self::LocaleUnderscore->value => 'Locale Code (_)',
17+
self::LocaleHyphen->value => 'Locale Code (-)',
18+
self::Custom->value => 'Custom',
19+
];
20+
21+
case StoreCode = 'store_code';
22+
case CountryCode = 'country_code';
23+
case LocaleUnderscore = 'locale_underscore';
24+
case LocaleHyphen = 'locale_hyphen';
25+
case Custom = 'custom';
26+
27+
public function getLabel(): Phrase
28+
{
29+
return new Phrase(self::PHRASES[$this->value]);
30+
}
31+
}

Model/Config/Source/PathTypes.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Model\Config\Source;
8+
9+
use Magento\Framework\Data\OptionSourceInterface;
10+
use Opengento\StorePathUrl\Model\Config\PathType;
11+
12+
use function array_map;
13+
14+
class PathTypes implements OptionSourceInterface
15+
{
16+
private ?array $options = null;
17+
18+
public function toOptionArray(): array
19+
{
20+
return $this->options ??= array_map(
21+
static fn(PathType $pathType): array => ['label' => $pathType->getLabel(), 'value' => $pathType->value],
22+
PathType::cases()
23+
);
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Model\StoreSwitcher;
8+
9+
use Magento\Store\Api\Data\StoreInterface;
10+
use Magento\Store\Model\StoreSwitcherInterface;
11+
use Opengento\StorePathUrl\Model\Config;
12+
use Opengento\StorePathUrl\Service\UriUtils;
13+
14+
class ApplyStorePath implements StoreSwitcherInterface
15+
{
16+
public function __construct(
17+
private Config $config,
18+
private UriUtils $uriUtils
19+
) {}
20+
21+
public function switch(StoreInterface $fromStore, StoreInterface $targetStore, string $redirectUrl): string
22+
{
23+
return $this->config->isEnabled() ? $this->uriUtils->replaceStoreCode($redirectUrl, $targetStore) : $redirectUrl;
24+
}
25+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Model\StoreSwitcher;
8+
9+
use Magento\Store\Api\Data\StoreInterface;
10+
use Magento\Store\Model\StoreSwitcherInterface;
11+
use Opengento\StorePathUrl\Model\Config;
12+
use Opengento\StorePathUrl\Service\UriUtils;
13+
14+
class RevertStorePath implements StoreSwitcherInterface
15+
{
16+
public function __construct(
17+
private Config $config,
18+
private UriUtils $uriUtils
19+
) {}
20+
21+
public function switch(StoreInterface $fromStore, StoreInterface $targetStore, string $redirectUrl): string
22+
{
23+
return $this->config->isEnabled() ? $this->uriUtils->replacePathCode($redirectUrl, $targetStore) : $redirectUrl;
24+
}
25+
}

Plugin/App/Request/PathInfo.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
*/
5+
declare(strict_types=1);
6+
7+
namespace Opengento\StorePathUrl\Plugin\App\Request;
8+
9+
use Magento\Framework\App\Request\PathInfo as PathInfoSubject;
10+
use Opengento\StorePathUrl\Service\StorePathFixer;
11+
use Opengento\StorePathUrl\Model\Config;
12+
13+
class PathInfo
14+
{
15+
public function __construct(
16+
private Config $config,
17+
private StorePathFixer $storePathFixer
18+
) {}
19+
20+
public function beforeGetPathInfo(PathInfoSubject $subject, string $requestUri, string $baseUrl): array
21+
{
22+
if ($this->config->isEnabled()) {
23+
$requestUri = $this->storePathFixer->fix($baseUrl, $requestUri);
24+
}
25+
26+
return [$requestUri, $baseUrl];
27+
}
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright © OpenGento, All rights reserved.
7+
*/
8+
9+
namespace Opengento\StorePathUrl\Plugin\App\Request;
10+
11+
use Magento\Framework\App\Request\Http;
12+
use Magento\Store\App\Request\StorePathInfoValidator as StorePathInfoValidatorSubject;
13+
use Opengento\StorePathUrl\Model\Config;
14+
use Opengento\StorePathUrl\Service\StorePathFixer;
15+
16+
class StorePathInfoValidator
17+
{
18+
public function __construct(
19+
private Config $config,
20+
private StorePathFixer $storePathFixer
21+
) {}
22+
23+
public function beforeGetValidStoreCode(
24+
StorePathInfoValidatorSubject $subject,
25+
Http $request,
26+
string $pathInfo = ''
27+
): array {
28+
if ($pathInfo !== '' && $this->config->isEnabled()) {
29+
$pathInfo = $this->storePathFixer->fix($request->getBaseUrl(), $pathInfo);
30+
}
31+
32+
return [$request, $pathInfo];
33+
}
34+
}

0 commit comments

Comments
 (0)