Skip to content

Commit 87b0a4b

Browse files
authored
Merge pull request #5172 from magento-engcom/2.4-develop-forward-port-2
[Magento Community Engineering] Community Contributions - GraphQL - 2.4-develop forward-port
2 parents 3e23510 + 1690aae commit 87b0a4b

File tree

14 files changed

+673
-16
lines changed

14 files changed

+673
-16
lines changed

app/code/Magento/CustomerGraphQl/Model/Customer/ValidateCustomerData.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
namespace Magento\CustomerGraphQl\Model\Customer;
99

1010
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
use Magento\Framework\Validator\EmailAddress as EmailAddressValidator;
1112

1213
/**
13-
* Class ValidateCustomerData
14+
* Customer data validation used during customer account creation and updating
1415
*/
1516
class ValidateCustomerData
1617
{
@@ -21,14 +22,23 @@ class ValidateCustomerData
2122
*/
2223
private $getAllowedCustomerAttributes;
2324

25+
/**
26+
* @var EmailAddressValidator
27+
*/
28+
private $emailAddressValidator;
29+
2430
/**
2531
* ValidateCustomerData constructor.
2632
*
2733
* @param GetAllowedCustomerAttributes $getAllowedCustomerAttributes
34+
* @param EmailAddressValidator $emailAddressValidator
2835
*/
29-
public function __construct(GetAllowedCustomerAttributes $getAllowedCustomerAttributes)
30-
{
36+
public function __construct(
37+
GetAllowedCustomerAttributes $getAllowedCustomerAttributes,
38+
EmailAddressValidator $emailAddressValidator
39+
) {
3140
$this->getAllowedCustomerAttributes = $getAllowedCustomerAttributes;
41+
$this->emailAddressValidator = $emailAddressValidator;
3242
}
3343

3444
/**
@@ -59,5 +69,11 @@ public function execute(array $customerData): void
5969
__('Required parameters are missing: %1', [implode(', ', $errorInput)])
6070
);
6171
}
72+
73+
if (isset($customerData['email']) && !$this->emailAddressValidator->isValid($customerData['email'])) {
74+
throw new GraphQlInputException(
75+
__('"%1" is not a valid email address.', $customerData['email'])
76+
);
77+
}
6278
}
6379
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider;
9+
10+
use Magento\Swatches\Helper\Data as SwatchData;
11+
use Magento\Swatches\Helper\Media as SwatchesMedia;
12+
use Magento\Swatches\Model\Swatch;
13+
14+
/**
15+
* Data provider for options swatches.
16+
*/
17+
class SwatchDataProvider
18+
{
19+
/**
20+
* @var SwatchData
21+
*/
22+
private $swatchHelper;
23+
24+
/**
25+
* @var SwatchesMedia
26+
*/
27+
private $swatchMediaHelper;
28+
29+
/**
30+
* SwatchDataProvider constructor.
31+
*
32+
* @param SwatchData $swatchHelper
33+
* @param SwatchesMedia $swatchMediaHelper
34+
*/
35+
public function __construct(
36+
SwatchData $swatchHelper,
37+
SwatchesMedia $swatchMediaHelper
38+
) {
39+
$this->swatchHelper = $swatchHelper;
40+
$this->swatchMediaHelper = $swatchMediaHelper;
41+
}
42+
43+
/**
44+
* Returns swatch data by option ID.
45+
*
46+
* @param string $optionId
47+
* @return array|null
48+
*/
49+
public function getData(string $optionId): ?array
50+
{
51+
$swatches = $this->swatchHelper->getSwatchesByOptionsId([$optionId]);
52+
if (!isset($swatches[$optionId]['type'], $swatches[$optionId]['value'])) {
53+
return null;
54+
}
55+
$type = (int)$swatches[$optionId]['type'];
56+
$value = $swatches[$optionId]['value'];
57+
$data = ['value' => $value, 'type' => $type];
58+
if ($type === Swatch::SWATCH_TYPE_VISUAL_IMAGE) {
59+
$data['thumbnail'] = $this->swatchMediaHelper->getSwatchAttributeImage(
60+
Swatch::SWATCH_THUMBNAIL_NAME,
61+
$value
62+
);
63+
}
64+
return $data;
65+
}
66+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\ResolverInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13+
use Magento\SwatchesGraphQl\Model\Resolver\Product\Options\DataProvider\SwatchDataProvider;
14+
15+
/**
16+
* Class SwatchData
17+
*
18+
* Product swatch data resolver, used for GraphQL request processing
19+
*/
20+
class SwatchData implements ResolverInterface
21+
{
22+
/**
23+
* @var SwatchDataProvider
24+
*/
25+
private $swatchDataProvider;
26+
27+
/**
28+
* SwatchData constructor.
29+
*
30+
* @param SwatchDataProvider $swatchDataProvider
31+
*/
32+
public function __construct(
33+
SwatchDataProvider $swatchDataProvider
34+
) {
35+
$this->swatchDataProvider = $swatchDataProvider;
36+
}
37+
38+
/**
39+
* @inheritdoc
40+
*/
41+
public function resolve(
42+
Field $field,
43+
$context,
44+
ResolveInfo $info,
45+
array $value = null,
46+
array $args = null
47+
) {
48+
return $this->swatchDataProvider->getData($value['value_index']);
49+
}
50+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\SwatchesGraphQl\Model\Resolver\Product\Options;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface;
12+
use Magento\Swatches\Model\Swatch;
13+
14+
/**
15+
* Resolver for swatch data interface.
16+
*/
17+
class SwatchDataTypeResolver implements TypeResolverInterface
18+
{
19+
/**
20+
* @inheritdoc
21+
*/
22+
public function resolveType(array $data): string
23+
{
24+
switch ($data['type']) {
25+
case Swatch::SWATCH_TYPE_TEXTUAL:
26+
return 'TextSwatchData';
27+
case Swatch::SWATCH_TYPE_VISUAL_COLOR:
28+
return 'ColorSwatchData';
29+
case Swatch::SWATCH_TYPE_VISUAL_IMAGE:
30+
return 'ImageSwatchData';
31+
default:
32+
throw new LocalizedException(__('Unsupported swatch type'));
33+
}
34+
}
35+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
</argument>
1717
</arguments>
1818
</type>
19-
</config>
19+
</config>

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,24 @@ type SwatchLayerFilterItem implements LayerFilterItemInterface, SwatchLayerFilte
2626
type SwatchData {
2727
type: String @doc(description: "Type of swatch filter item: 1 - text, 2 - image")
2828
value: String @doc(description: "Value for swatch item (text or image link)")
29-
}
29+
}
30+
31+
type ConfigurableProductOptionsValues {
32+
swatch_data: SwatchDataInterface @doc(description: "Swatch data for configurable product option") @resolver(class: "Magento\\SwatchesGraphQl\\Model\\Resolver\\Product\\Options\\SwatchData")
33+
}
34+
35+
interface SwatchDataInterface @typeResolver(class: "Magento\\SwatchesGraphQl\\Model\\Resolver\\Product\\Options\\SwatchDataTypeResolver") {
36+
value: String @doc(description: "Value of swatch item (HEX color code, image link or textual value)")
37+
}
38+
39+
type ImageSwatchData implements SwatchDataInterface {
40+
thumbnail: String @doc(description: "Thumbnail swatch image URL")
41+
}
42+
43+
type TextSwatchData implements SwatchDataInterface {
44+
45+
}
46+
47+
type ColorSwatchData implements SwatchDataInterface {
48+
49+
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Customer/CreateCustomerTest.php

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,25 @@ public function testCreateCustomerIfEmailMissed()
172172
}
173173

174174
/**
175-
* @expectedException \Exception
176-
* @expectedExceptionMessage "Email" is not a valid email address.
175+
* @dataProvider invalidEmailAddressDataProvider
176+
*
177+
* @param string $email
178+
* @throws \Exception
177179
*/
178-
public function testCreateCustomerIfEmailIsNotValid()
180+
public function testCreateCustomerIfEmailIsNotValid(string $email)
179181
{
180-
$newFirstname = 'Richard';
181-
$newLastname = 'Rowe';
182-
$currentPassword = 'test123#';
183-
$newEmail = 'email';
182+
$firstname = 'Richard';
183+
$lastname = 'Rowe';
184+
$password = 'test123#';
184185

185186
$query = <<<QUERY
186187
mutation {
187188
createCustomer(
188189
input: {
189-
firstname: "{$newFirstname}"
190-
lastname: "{$newLastname}"
191-
email: "{$newEmail}"
192-
password: "{$currentPassword}"
190+
firstname: "{$firstname}"
191+
lastname: "{$lastname}"
192+
email: "{$email}"
193+
password: "{$password}"
193194
is_subscribed: true
194195
}
195196
) {
@@ -203,9 +204,29 @@ public function testCreateCustomerIfEmailIsNotValid()
203204
}
204205
}
205206
QUERY;
207+
$this->expectExceptionMessage('"' . $email . '" is not a valid email address.');
206208
$this->graphQlMutation($query);
207209
}
208210

211+
/**
212+
* @return array
213+
*/
214+
public function invalidEmailAddressDataProvider(): array
215+
{
216+
return [
217+
['plainaddress'],
218+
['jØrgen@somedomain.com'],
219+
['#@%^%#$@#$@#.com'],
220+
['@example.com'],
221+
['Joe Smith <email@example.com>'],
222+
['email.example.com'],
223+
['email@example@example.com'],
224+
['email@example.com (Joe Smith)'],
225+
['email@example'],
226+
['“email”@example.com'],
227+
];
228+
}
229+
209230
/**
210231
* @expectedException \Exception
211232
* @expectedExceptionMessage Field "test123" is not defined by type CustomerInput.

0 commit comments

Comments
 (0)