Skip to content

Commit 0794521

Browse files
PWA-1441 Support alternative locale URL redirects (#10)
* PWA-1441 adding after plugin to fetch good URL for current entity * PWA-1441 fixing coding standards, adding unit test * PWA-1441 updating url arg to be same as parent functionality * PWA-1441: Switching stores results in error page if slug changes between stores * PWA-1441: Switching stores results in error page if slug changes between stores * PWA-1441: Switching stores results in error page if slug changes between stores * PWA-1441: Switching stores results in error page if slug changes between stores Co-authored-by: Ievgen Kolesov <ikolesov@adobe.com>
1 parent 5c9abce commit 0794521

File tree

9 files changed

+596
-1
lines changed

9 files changed

+596
-1
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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\UrlRewriteGraphQlPwa\Plugin\UrlResolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\Resolver\ContextInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13+
use Magento\Store\Api\StoreRepositoryInterface;
14+
use Magento\UrlRewrite\Model\UrlFinderInterface;
15+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
16+
use Magento\UrlRewriteGraphQl\Model\DataProvider\EntityDataProviderComposite;
17+
use Magento\UrlRewriteGraphQl\Model\Resolver\Route;
18+
19+
class RoutePlugin
20+
{
21+
/** @var UrlFinderInterface */
22+
private $urlFinder;
23+
24+
/** @var StoreRepositoryInterface */
25+
private $storeRepository;
26+
27+
/** @var EntityDataProviderComposite */
28+
private $entityDataProviderComposite;
29+
30+
/**
31+
* @param UrlFinderInterface $urlFinder
32+
* @param StoreRepositoryInterface $storeRepository
33+
* @param EntityDataProviderComposite $entityDataProviderComposite
34+
*/
35+
public function __construct(
36+
UrlFinderInterface $urlFinder,
37+
StoreRepositoryInterface $storeRepository,
38+
EntityDataProviderComposite $entityDataProviderComposite
39+
) {
40+
$this->urlFinder = $urlFinder;
41+
$this->storeRepository = $storeRepository;
42+
$this->entityDataProviderComposite = $entityDataProviderComposite;
43+
}
44+
45+
/**
46+
* Determine if alternative locale URL is available for redirection
47+
*
48+
* @param Route $subject
49+
* @param array<scalar>|null $result
50+
* @param Field $field
51+
* @param ContextInterface $context
52+
* @param ResolveInfo $info
53+
* @param array<scalar>|null $value
54+
* @param array<scalar>|null $args
55+
*
56+
* @return array<scalar>|null
57+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
58+
*/
59+
public function afterResolve(
60+
Route $subject,
61+
?array $result,
62+
Field $field,
63+
ContextInterface $context,
64+
ResolveInfo $info,
65+
?array $value = null,
66+
?array $args = null
67+
): ?array {
68+
if ($result !== null) {
69+
return $result;
70+
}
71+
72+
// phpcs:ignore Magento2.Functions.DiscouragedFunction
73+
$urlParts = parse_url($args['url']);
74+
$url = $urlParts['path'] ?? $args['url'];
75+
76+
if ($url !== '/' && strpos($url, '/') === 0) {
77+
$url = ltrim($url, '/');
78+
}
79+
80+
$targetStoreId = (int) $context->getExtensionAttributes()->getStore()->getId();
81+
82+
$otherStores = $this->getOtherStoreIds($targetStoreId);
83+
if (empty($otherStores)) {
84+
return null;
85+
}
86+
87+
$validUrlEntity = $this->getUrlEntity($url, $otherStores);
88+
if ($validUrlEntity === null) {
89+
return null;
90+
}
91+
92+
$targetStoreView = $this->urlFinder->findOneByData(
93+
[
94+
UrlRewrite::ENTITY_ID => $validUrlEntity->getEntityId(),
95+
UrlRewrite::ENTITY_TYPE => $validUrlEntity->getEntityType(),
96+
UrlRewrite::TARGET_PATH => $validUrlEntity->getTargetPath(),
97+
UrlRewrite::STORE_ID => $targetStoreId,
98+
]
99+
);
100+
101+
if ($targetStoreView === null) {
102+
return null;
103+
}
104+
105+
$targetUrl = $targetStoreView->getRequestPath();
106+
107+
$type = $this->sanitizeType($targetStoreView->getEntityType());
108+
109+
$result = $this->entityDataProviderComposite->getData(
110+
$type,
111+
(int) $targetStoreView->getEntityId(),
112+
$info,
113+
$targetStoreId
114+
);
115+
116+
$result['redirect_code'] = 302;
117+
$result['relative_url'] = $targetUrl;
118+
$result['type'] = $type;
119+
120+
return $result;
121+
}
122+
123+
/**
124+
* Get UrlRewrite entity
125+
*
126+
* @param string $url
127+
* @param int[] $storeIds
128+
* @return UrlRewrite|null
129+
*/
130+
private function getUrlEntity(string $url, array $storeIds): ?UrlRewrite
131+
{
132+
$validUrlEntity = null;
133+
foreach ($storeIds as $storeId) {
134+
$validUrlEntity = $this->urlFinder->findOneByData(
135+
[
136+
UrlRewrite::REQUEST_PATH => $url,
137+
UrlRewrite::STORE_ID => $storeId,
138+
]
139+
);
140+
141+
if ($validUrlEntity !== null) {
142+
break;
143+
}
144+
}
145+
146+
return $validUrlEntity;
147+
}
148+
149+
/**
150+
* Get store IDs other than current
151+
*
152+
* @param int $currentStoreId
153+
* @return int[]
154+
*/
155+
private function getOtherStoreIds(int $currentStoreId): array
156+
{
157+
$stores = $this->storeRepository->getList();
158+
$otherStores = [];
159+
160+
foreach ($stores as $store) {
161+
$storeId = (int) $store->getId();
162+
163+
if ($storeId === 0 || ($storeId === $currentStoreId) || !$store->getIsActive()) {
164+
continue;
165+
}
166+
167+
$otherStores[] = $storeId;
168+
}
169+
170+
return $otherStores;
171+
}
172+
173+
/**
174+
* Sanitize the type to fit schema specifications
175+
*
176+
* @param string $type
177+
* @return string
178+
*/
179+
private function sanitizeType(string $type): string
180+
{
181+
return strtoupper(str_replace('-', '_', $type));
182+
}
183+
}

UrlRewriteGraphQlPwa/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# UrlRewriteGraphQl PWA
2+
3+
**UrlRewriteGraphQl PWA** extends the base URL Rewrite GraphQL support for PWA Studio

0 commit comments

Comments
 (0)