Skip to content

Commit 2d48fbc

Browse files
authored
ENGCOM-5606: magento#271 [My Account] Add support of Customer attributes magento#489
2 parents dc47068 + 2c39ba3 commit 2d48fbc

File tree

6 files changed

+277
-7
lines changed

6 files changed

+277
-7
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Framework\Api\DataObjectHelper;
1414
use Magento\Framework\Exception\LocalizedException;
1515
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
16+
use Magento\Framework\Reflection\DataObjectProcessor;
1617
use Magento\Store\Api\Data\StoreInterface;
1718

1819
/**
@@ -41,21 +42,39 @@ class CreateCustomerAccount
4142
private $changeSubscriptionStatus;
4243

4344
/**
45+
* @var ValidateCustomerData
46+
*/
47+
private $validateCustomerData;
48+
49+
/**
50+
* @var DataObjectProcessor
51+
*/
52+
private $dataObjectProcessor;
53+
54+
/**
55+
* CreateCustomerAccount constructor.
56+
*
4457
* @param DataObjectHelper $dataObjectHelper
4558
* @param CustomerInterfaceFactory $customerFactory
4659
* @param AccountManagementInterface $accountManagement
4760
* @param ChangeSubscriptionStatus $changeSubscriptionStatus
61+
* @param DataObjectProcessor $dataObjectProcessor
62+
* @param ValidateCustomerData $validateCustomerData
4863
*/
4964
public function __construct(
5065
DataObjectHelper $dataObjectHelper,
5166
CustomerInterfaceFactory $customerFactory,
5267
AccountManagementInterface $accountManagement,
53-
ChangeSubscriptionStatus $changeSubscriptionStatus
68+
ChangeSubscriptionStatus $changeSubscriptionStatus,
69+
DataObjectProcessor $dataObjectProcessor,
70+
ValidateCustomerData $validateCustomerData
5471
) {
5572
$this->dataObjectHelper = $dataObjectHelper;
5673
$this->customerFactory = $customerFactory;
5774
$this->accountManagement = $accountManagement;
5875
$this->changeSubscriptionStatus = $changeSubscriptionStatus;
76+
$this->validateCustomerData = $validateCustomerData;
77+
$this->dataObjectProcessor = $dataObjectProcessor;
5978
}
6079

6180
/**
@@ -91,6 +110,15 @@ public function execute(array $data, StoreInterface $store): CustomerInterface
91110
private function createAccount(array $data, StoreInterface $store): CustomerInterface
92111
{
93112
$customerDataObject = $this->customerFactory->create();
113+
/**
114+
* Add required attributes for customer entity
115+
*/
116+
$requiredDataAttributes = $this->dataObjectProcessor->buildOutputDataArray(
117+
$customerDataObject,
118+
CustomerInterface::class
119+
);
120+
$data = array_merge($requiredDataAttributes, $data);
121+
$this->validateCustomerData->execute($data);
94122
$this->dataObjectHelper->populateWithArray(
95123
$customerDataObject,
96124
$data,
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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\CustomerGraphQl\Model\Customer;
9+
10+
use Magento\Customer\Api\CustomerMetadataManagementInterface;
11+
use Magento\Customer\Api\Data\CustomerInterface;
12+
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
13+
use Magento\Eav\Model\AttributeRepository;
14+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
15+
use Magento\Framework\Api\SearchCriteriaBuilder;
16+
use Magento\Framework\Exception\InputException;
17+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
18+
use Magento\Framework\Reflection\DataObjectProcessor;
19+
20+
/**
21+
* Get allowed address attributes
22+
*/
23+
class GetAllowedCustomerAttributes
24+
{
25+
/**
26+
* @var AttributeRepository
27+
*/
28+
private $attributeRepository;
29+
30+
/**
31+
* @var CustomerInterfaceFactory\
32+
*/
33+
private $customerDataFactory;
34+
35+
/**
36+
* @var DataObjectProcessor
37+
*/
38+
private $dataObjectProcessor;
39+
40+
/**
41+
* @var SearchCriteriaBuilder
42+
*/
43+
private $searchCriteriaBuilder;
44+
45+
/**
46+
* GetAllowedCustomerAttributes constructor.
47+
*
48+
* @param AttributeRepository $attributeRepository
49+
* @param CustomerInterfaceFactory $customerDataFactory
50+
* @param DataObjectProcessor $dataObjectProcessor
51+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
52+
*/
53+
public function __construct(
54+
AttributeRepository $attributeRepository,
55+
CustomerInterfaceFactory $customerDataFactory,
56+
DataObjectProcessor $dataObjectProcessor,
57+
SearchCriteriaBuilder $searchCriteriaBuilder
58+
) {
59+
$this->attributeRepository = $attributeRepository;
60+
$this->customerDataFactory = $customerDataFactory;
61+
$this->dataObjectProcessor = $dataObjectProcessor;
62+
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
63+
}
64+
65+
/**
66+
* Get allowed customer attributes
67+
*
68+
* @param array $attributeKeys
69+
*
70+
* @throws GraphQlInputException
71+
*
72+
* @return AbstractAttribute[]
73+
*/
74+
public function execute($attributeKeys): array
75+
{
76+
$this->searchCriteriaBuilder->addFilter('attribute_code', $attributeKeys, 'in');
77+
$searchCriteria = $this->searchCriteriaBuilder->create();
78+
try {
79+
$attributesSearchResult = $this->attributeRepository->getList(
80+
CustomerMetadataManagementInterface::ENTITY_TYPE_CUSTOMER,
81+
$searchCriteria
82+
);
83+
} catch (InputException $exception) {
84+
throw new GraphQlInputException(__($exception->getMessage()));
85+
}
86+
87+
/** @var AbstractAttribute[] $attributes */
88+
$attributes = $attributesSearchResult->getItems();
89+
90+
foreach ($attributes as $index => $attribute) {
91+
if (false === $attribute->getIsVisibleOnFront()) {
92+
unset($attributes[$index]);
93+
}
94+
}
95+
96+
return $attributes;
97+
}
98+
}

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77

88
namespace Magento\CustomerGraphQl\Model\Customer;
99

10+
use Magento\Customer\Api\Data\CustomerInterface;
11+
use Magento\Framework\Exception\NoSuchEntityException;
1012
use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException;
1113
use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException;
1214
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13-
use Magento\Customer\Api\Data\CustomerInterface;
15+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1416
use Magento\Framework\Api\DataObjectHelper;
1517
use Magento\Store\Api\Data\StoreInterface;
1618

@@ -41,6 +43,11 @@ class UpdateCustomerAccount
4143
*/
4244
private $changeSubscriptionStatus;
4345

46+
/**
47+
* @var ValidateCustomerData
48+
*/
49+
private $validateCustomerData;
50+
4451
/**
4552
* @var array
4653
*/
@@ -51,24 +58,27 @@ class UpdateCustomerAccount
5158
* @param CheckCustomerPassword $checkCustomerPassword
5259
* @param DataObjectHelper $dataObjectHelper
5360
* @param ChangeSubscriptionStatus $changeSubscriptionStatus
61+
* @param ValidateCustomerData $validateCustomerData
5462
* @param array $restrictedKeys
5563
*/
5664
public function __construct(
5765
SaveCustomer $saveCustomer,
5866
CheckCustomerPassword $checkCustomerPassword,
5967
DataObjectHelper $dataObjectHelper,
6068
ChangeSubscriptionStatus $changeSubscriptionStatus,
69+
ValidateCustomerData $validateCustomerData,
6170
array $restrictedKeys = []
6271
) {
6372
$this->saveCustomer = $saveCustomer;
6473
$this->checkCustomerPassword = $checkCustomerPassword;
6574
$this->dataObjectHelper = $dataObjectHelper;
6675
$this->restrictedKeys = $restrictedKeys;
6776
$this->changeSubscriptionStatus = $changeSubscriptionStatus;
77+
$this->validateCustomerData = $validateCustomerData;
6878
}
6979

7080
/**
71-
* Update customer account data
81+
* Update customer account
7282
*
7383
* @param CustomerInterface $customer
7484
* @param array $data
@@ -77,7 +87,7 @@ public function __construct(
7787
* @throws GraphQlAlreadyExistsException
7888
* @throws GraphQlAuthenticationException
7989
* @throws GraphQlInputException
80-
* @throws \Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException
90+
* @throws GraphQlNoSuchEntityException
8191
*/
8292
public function execute(CustomerInterface $customer, array $data, StoreInterface $store): void
8393
{
@@ -89,11 +99,15 @@ public function execute(CustomerInterface $customer, array $data, StoreInterface
8999
$this->checkCustomerPassword->execute($data['password'], (int)$customer->getId());
90100
$customer->setEmail($data['email']);
91101
}
92-
102+
$this->validateCustomerData->execute($data);
93103
$filteredData = array_diff_key($data, array_flip($this->restrictedKeys));
94104
$this->dataObjectHelper->populateWithArray($customer, $filteredData, CustomerInterface::class);
95105

96-
$customer->setStoreId($store->getId());
106+
try {
107+
$customer->setStoreId($store->getId());
108+
} catch (NoSuchEntityException $exception) {
109+
throw new GraphQlNoSuchEntityException(__($exception->getMessage()), $exception);
110+
}
97111

98112
$this->saveCustomer->execute($customer);
99113

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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\CustomerGraphQl\Model\Customer;
9+
10+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
12+
/**
13+
* Class ValidateCustomerData
14+
*/
15+
class ValidateCustomerData
16+
{
17+
/**
18+
* Get allowed/required customer attributes
19+
*
20+
* @var GetAllowedCustomerAttributes
21+
*/
22+
private $getAllowedCustomerAttributes;
23+
24+
/**
25+
* ValidateCustomerData constructor.
26+
*
27+
* @param GetAllowedCustomerAttributes $getAllowedCustomerAttributes
28+
*/
29+
public function __construct(GetAllowedCustomerAttributes $getAllowedCustomerAttributes)
30+
{
31+
$this->getAllowedCustomerAttributes = $getAllowedCustomerAttributes;
32+
}
33+
34+
/**
35+
* Validate customer data
36+
*
37+
* @param array $customerData
38+
*
39+
* @return void
40+
*
41+
* @throws GraphQlInputException
42+
*/
43+
public function execute(array $customerData): void
44+
{
45+
$attributes = $this->getAllowedCustomerAttributes->execute(array_keys($customerData));
46+
$errorInput = [];
47+
48+
foreach ($attributes as $attributeInfo) {
49+
if ($attributeInfo->getIsRequired()
50+
&& (!isset($customerData[$attributeInfo->getAttributeCode()])
51+
|| $customerData[$attributeInfo->getAttributeCode()] == '')
52+
) {
53+
$errorInput[] = $attributeInfo->getDefaultFrontendLabel();
54+
}
55+
}
56+
57+
if ($errorInput) {
58+
throw new GraphQlInputException(
59+
__('Required parameters are missing: %1', [implode(', ', $errorInput)])
60+
);
61+
}
62+
}
63+
}

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public function testCreateCustomerIfInputDataIsEmpty()
139139

140140
/**
141141
* @expectedException \Exception
142-
* @expectedExceptionMessage The customer email is missing. Enter and try again.
142+
* @expectedExceptionMessage Required parameters are missing: Email
143143
*/
144144
public function testCreateCustomerIfEmailMissed()
145145
{
@@ -241,6 +241,41 @@ public function testCreateCustomerIfPassedAttributeDosNotExistsInCustomerInput()
241241
$this->graphQlMutation($query);
242242
}
243243

244+
/**
245+
* @expectedException \Exception
246+
* @expectedExceptionMessage Required parameters are missing: First Name
247+
*/
248+
public function testCreateCustomerIfNameEmpty()
249+
{
250+
$newEmail = 'customer_created' . rand(1, 2000000) . '@example.com';
251+
$newFirstname = '';
252+
$newLastname = 'Rowe';
253+
$currentPassword = 'test123#';
254+
255+
$query = <<<QUERY
256+
mutation {
257+
createCustomer(
258+
input: {
259+
email: "{$newEmail}"
260+
firstname: "{$newFirstname}"
261+
lastname: "{$newLastname}"
262+
password: "{$currentPassword}"
263+
is_subscribed: true
264+
}
265+
) {
266+
customer {
267+
id
268+
firstname
269+
lastname
270+
email
271+
is_subscribed
272+
}
273+
}
274+
}
275+
QUERY;
276+
$this->graphQlMutation($query);
277+
}
278+
244279
public function tearDown()
245280
{
246281
$newEmail = '[email protected]';

0 commit comments

Comments
 (0)