Skip to content

Commit bdde24b

Browse files
authored
Merge pull request #6022 from magento-obsessive-owls/PWA-805-group
[Owls] PWA-805: Expose localization system / store config from GraphQL
2 parents 4930963 + 2d34a2f commit bdde24b

File tree

16 files changed

+673
-7
lines changed

16 files changed

+673
-7
lines changed

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ public function getStoreByWebsiteId($websiteId)
4949
*
5050
* @param int $websiteId
5151
* @param bool $available
52+
* @param int|null $storeGroupId
5253
* @return array
5354
*/
54-
public function getWebsiteStores(int $websiteId, bool $available = false): array
55+
public function getWebsiteStores(int $websiteId, bool $available = false, int $storeGroupId = null): array
5556
{
5657
$connection = $this->resource->getConnection();
5758
$storeTable = $this->resource->getTableName('store');
@@ -60,6 +61,13 @@ public function getWebsiteStores(int $websiteId, bool $available = false): array
6061
$websiteId
6162
);
6263

64+
if ($storeGroupId) {
65+
$storeSelect = $storeSelect->where(
66+
'group_id = ?',
67+
$storeGroupId
68+
);
69+
}
70+
6371
if ($available) {
6472
$storeSelect = $storeSelect->where(
6573
'is_active = 1'

app/code/Magento/StoreGraphQl/Model/Resolver/AvailableStoresResolver.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ public function resolve(
4141
array $value = null,
4242
array $args = null
4343
) {
44+
$storeGroupId = !empty($args['useCurrentGroup']) ?
45+
(int)$context->getExtensionAttributes()->getStore()->getStoreGroupId() :
46+
null;
4447
return $this->storeConfigDataProvider->getAvailableStoreConfig(
45-
(int)$context->getExtensionAttributes()->getStore()->getWebsiteId()
48+
(int)$context->getExtensionAttributes()->getStore()->getWebsiteId(),
49+
$storeGroupId
4650
);
4751
}
4852
}

app/code/Magento/StoreGraphQl/Model/Resolver/Store/StoreConfigDataProvider.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ public function getStoreConfigData(StoreInterface $store): array
7373
* Get available website stores
7474
*
7575
* @param int $websiteId
76+
* @param int|null $storeGroupId
7677
* @return array
7778
*/
78-
public function getAvailableStoreConfig(int $websiteId): array
79+
public function getAvailableStoreConfig(int $websiteId, int $storeGroupId = null): array
7980
{
80-
$websiteStores = $this->storeWebsiteRelation->getWebsiteStores($websiteId, true);
81+
$websiteStores = $this->storeWebsiteRelation->getWebsiteStores($websiteId, true, $storeGroupId);
8182
$storeCodes = array_column($websiteStores, 'code');
8283

8384
$storeConfigs = $this->storeConfigManager->getStoreConfigs($storeCodes);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\StoreGraphQl\Plugin;
8+
9+
use Magento\Framework\App\AreaInterface;
10+
use Magento\Framework\App\AreaList;
11+
use Magento\Framework\App\State;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\Mail\Template\TransportBuilder;
15+
use Magento\Store\Model\App\Emulation;
16+
use Magento\Store\Model\StoreManagerInterface;
17+
18+
/**
19+
* Emulate the correct store when GraphQL is sending an email
20+
*/
21+
class LocalizeEmail
22+
{
23+
/**
24+
* @var StoreManagerInterface
25+
*/
26+
private $storeManager;
27+
28+
/**
29+
* @var Emulation
30+
*/
31+
private $emulation;
32+
33+
/**
34+
* @var AreaList
35+
*/
36+
private $areaList;
37+
38+
/**
39+
* @var State
40+
*/
41+
private $appState;
42+
43+
/**
44+
* @param StoreManagerInterface $storeManager
45+
* @param Emulation $emulation
46+
* @param AreaList $areaList
47+
* @param State $appState
48+
*/
49+
public function __construct(
50+
StoreManagerInterface $storeManager,
51+
Emulation $emulation,
52+
AreaList $areaList,
53+
State $appState
54+
) {
55+
$this->storeManager = $storeManager;
56+
$this->emulation = $emulation;
57+
$this->areaList = $areaList;
58+
$this->appState = $appState;
59+
}
60+
61+
/**
62+
* Emulate the correct store during email preparation
63+
*
64+
* @param TransportBuilder $subject
65+
* @param \Closure $proceed
66+
* @return mixed
67+
* @throws NoSuchEntityException|LocalizedException
68+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
69+
*/
70+
public function aroundGetTransport(TransportBuilder $subject, \Closure $proceed)
71+
{
72+
// Load translations for the app
73+
$area = $this->areaList->getArea($this->appState->getAreaCode());
74+
$area->load(AreaInterface::PART_TRANSLATE);
75+
76+
$currentStore = $this->storeManager->getStore();
77+
$this->emulation->startEnvironmentEmulation($currentStore->getId());
78+
$output = $proceed();
79+
$this->emulation->stopEnvironmentEmulation();
80+
81+
return $output;
82+
}
83+
}

app/code/Magento/StoreGraphQl/etc/graphql/di.xml

+10
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,14 @@
2323
</argument>
2424
</arguments>
2525
</type>
26+
<type name="Magento\StoreGraphQl\Model\Resolver\Store\StoreConfigDataProvider">
27+
<arguments>
28+
<argument name="extendedConfigData" xsi:type="array">
29+
<item name="use_store_in_url" xsi:type="string">web/url/use_store</item>
30+
</argument>
31+
</arguments>
32+
</type>
33+
<type name="Magento\Framework\Mail\Template\TransportBuilder">
34+
<plugin name="graphQlEmulateEmail" type="Magento\StoreGraphQl\Plugin\LocalizeEmail" />
35+
</type>
2636
</config>

app/code/Magento/StoreGraphQl/etc/schema.graphqls

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
# See COPYING.txt for license details.
33
type Query {
44
storeConfig : StoreConfig @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\StoreConfigResolver") @doc(description: "The store config query") @cache(cacheable: false)
5-
availableStores: [StoreConfig] @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\AvailableStoresResolver") @doc(description: "Get a list of available store views and their config information.")
5+
availableStores(
6+
useCurrentGroup: Boolean @doc(description: "Filter store views by current store group")
7+
): [StoreConfig] @resolver(class: "Magento\\StoreGraphQl\\Model\\Resolver\\AvailableStoresResolver") @doc(description: "Get a list of available store views and their config information.")
68
}
79

810
type Website @doc(description: "Website is deprecated because it is should not be used on storefront. The type contains information about a website") {
@@ -32,4 +34,5 @@ type StoreConfig @doc(description: "The type contains information about a store
3234
secure_base_static_url : String @doc(description: "Secure base static URL for the store")
3335
secure_base_media_url : String @doc(description: "Secure base media URL for the store")
3436
store_name : String @doc(description: "Name of the store")
37+
use_store_in_url: Boolean @doc(description: "The configuration determines if the store code should be used in the URL")
3538
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Store/AvailableStoreConfigTest.php

+96
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public function testDefaultWebsiteAvailableStoreConfigs(): void
8787
secure_base_static_url,
8888
secure_base_media_url,
8989
store_name
90+
use_store_in_url
9091
}
9192
}
9293
QUERY;
@@ -126,6 +127,7 @@ public function testNonDefaultWebsiteAvailableStoreConfigs(): void
126127
secure_base_static_url,
127128
secure_base_media_url,
128129
store_name
130+
use_store_in_url
129131
}
130132
}
131133
QUERY;
@@ -167,5 +169,99 @@ private function validateStoreConfig(StoreConfigInterface $storeConfig, array $r
167169
$this->assertEquals($storeConfig->getSecureBaseStaticUrl(), $responseConfig['secure_base_static_url']);
168170
$this->assertEquals($storeConfig->getSecureBaseMediaUrl(), $responseConfig['secure_base_media_url']);
169171
$this->assertEquals($store->getName(), $responseConfig['store_name']);
172+
$this->assertEquals($store->isUseStoreInUrl(), $responseConfig['use_store_in_url']);
173+
}
174+
175+
/**
176+
* @magentoApiDataFixture Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
177+
* @magentoConfigFixture web/url/use_store 1
178+
*/
179+
public function testAllStoreConfigsWithCodeInUrlEnabled(): void
180+
{
181+
$storeConfigs = $this->storeConfigManager->getStoreConfigs(
182+
[
183+
'fixture_second_store',
184+
'fixture_third_store',
185+
'fixture_fourth_store',
186+
'fixture_fifth_store'
187+
]
188+
);
189+
190+
$query
191+
= <<<QUERY
192+
{
193+
availableStores(useCurrentGroup:false) {
194+
id,
195+
code,
196+
website_id,
197+
locale,
198+
base_currency_code,
199+
default_display_currency_code,
200+
timezone,
201+
weight_unit,
202+
base_url,
203+
base_link_url,
204+
base_static_url,
205+
base_media_url,
206+
secure_base_url,
207+
secure_base_link_url,
208+
secure_base_static_url,
209+
secure_base_media_url,
210+
store_name
211+
use_store_in_url
212+
}
213+
}
214+
QUERY;
215+
$headerMap = ['Store' => 'fixture_fifth_store'];
216+
$response = $this->graphQlQuery($query, [], '', $headerMap);
217+
218+
$this->assertArrayHasKey('availableStores', $response);
219+
$this->assertCount(4, $response['availableStores']);
220+
foreach ($response['availableStores'] as $key => $responseConfig) {
221+
$this->validateStoreConfig($storeConfigs[$key], $responseConfig);
222+
$this->assertEquals(true, $responseConfig['use_store_in_url']);
223+
}
224+
}
225+
226+
/**
227+
* @magentoApiDataFixture Magento/Store/_files/second_website_with_four_stores_divided_in_groups.php
228+
*/
229+
public function testCurrentGroupStoreConfigs(): void
230+
{
231+
$storeConfigs = $this->storeConfigManager->getStoreConfigs(['fixture_fourth_store', 'fixture_fifth_store']);
232+
233+
$query
234+
= <<<QUERY
235+
{
236+
availableStores(useCurrentGroup:true) {
237+
id,
238+
code,
239+
website_id,
240+
locale,
241+
base_currency_code,
242+
default_display_currency_code,
243+
timezone,
244+
weight_unit,
245+
base_url,
246+
base_link_url,
247+
base_static_url,
248+
base_media_url,
249+
secure_base_url,
250+
secure_base_link_url,
251+
secure_base_static_url,
252+
secure_base_media_url,
253+
store_name
254+
use_store_in_url
255+
}
256+
}
257+
QUERY;
258+
$headerMap = ['Store' => 'fixture_fifth_store'];
259+
$response = $this->graphQlQuery($query, [], '', $headerMap);
260+
261+
$this->assertArrayHasKey('availableStores', $response);
262+
$this->assertCount(2, $response['availableStores']);
263+
foreach ($response['availableStores'] as $key => $responseConfig) {
264+
$this->validateStoreConfig($storeConfigs[$key], $responseConfig);
265+
}
170266
}
171267
}

dev/tests/integration/framework/Magento/TestFramework/Annotation/ConfigFixture.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ protected function _assignConfigData(TestCase $test)
158158
self::ANNOTATION
159159
);
160160
foreach ($testAnnotations as $configPathAndValue) {
161-
if (preg_match('/^.+?(?=_store\s)/', $configPathAndValue, $matches)) {
161+
if (preg_match('/^[^\/]+?(?=_store\s)/', $configPathAndValue, $matches)) {
162162
$this->setStoreConfigValue($matches ?? [], $configPathAndValue);
163-
} elseif (preg_match('/^.+?(?=_website\s)/', $configPathAndValue, $matches)) {
163+
} elseif (preg_match('/^[^\/]+?(?=_website\s)/', $configPathAndValue, $matches)) {
164164
$this->setWebsiteConfigValue($matches ?? [], $configPathAndValue);
165165
} else {
166166
$this->setGlobalConfigValue($configPathAndValue);

0 commit comments

Comments
 (0)