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 \Resolver ;
9
+
10
+ use Magento \Authorization \Model \UserContextInterface ;
11
+ use Magento \Customer \Api \CustomerRepositoryInterface ;
12
+ use Magento \Customer \Api \Data \CustomerInterface ;
13
+ use Magento \Customer \Api \AddressMetadataManagementInterface ;
14
+ use Magento \Customer \Api \AddressRepositoryInterface ;
15
+ use Magento \Customer \Api \Data \AddressInterfaceFactory ;
16
+ use Magento \Customer \Api \Data \AddressInterface ;
17
+ use Magento \Customer \Api \Data \RegionInterfaceFactory ;
18
+ use Magento \Customer \Api \Data \AddressExtensionInterfaceFactory ;
19
+ use Magento \Framework \Api \AttributeInterfaceFactory ;
20
+ use Magento \Framework \GraphQl \Schema \Type \ResolveInfo ;
21
+ use Magento \Framework \GraphQl \Config \Element \Field ;
22
+ use Magento \Framework \GraphQl \Exception \GraphQlAuthorizationException ;
23
+ use Magento \Framework \GraphQl \Query \Resolver \ContextInterface ;
24
+ use Magento \Framework \GraphQl \Query \ResolverInterface ;
25
+ use Magento \Framework \GraphQl \Exception \GraphQlInputException ;
26
+ use Magento \Framework \GraphQl \Exception \GraphQlNoSuchEntityException ;
27
+ use Magento \Framework \Exception \NoSuchEntityException ;
28
+ use Magento \CustomerGraphQl \Model \Resolver \Address \AddressDataProvider ;
29
+ use Magento \Eav \Model \Config ;
30
+
31
+ /**
32
+ * Customers Address Update
33
+ */
34
+ class Address implements ResolverInterface
35
+ {
36
+ /**
37
+ * Customer address attributes
38
+ * @var array
39
+ */
40
+ const ADDRESS_ATTRIBUTES = [
41
+ AddressInterface::REGION ,
42
+ AddressInterface::REGION_ID ,
43
+ AddressInterface::COUNTRY_ID ,
44
+ AddressInterface::STREET ,
45
+ AddressInterface::COMPANY ,
46
+ AddressInterface::TELEPHONE ,
47
+ AddressInterface::FAX ,
48
+ AddressInterface::POSTCODE ,
49
+ AddressInterface::CITY ,
50
+ AddressInterface::FIRSTNAME ,
51
+ AddressInterface::LASTNAME ,
52
+ AddressInterface::MIDDLENAME ,
53
+ AddressInterface::PREFIX ,
54
+ AddressInterface::SUFFIX ,
55
+ AddressInterface::VAT_ID
56
+ ];
57
+
58
+ /**
59
+ * Input data key
60
+ */
61
+ const CUSTOM_ATTRIBUTE_KEY = 'custom_attributes ' ;
62
+ const EXTENSION_ATTRIBUTE_KEY = 'extension_attributes ' ;
63
+
64
+ /**
65
+ * Mutation Address type
66
+ */
67
+ const MUTATION_ADDRESS_CREATE = 'customerAddressCreate ' ;
68
+ const MUTATION_ADDRESS_UPDATE = 'customerAddressUpdate ' ;
69
+ const MUTATION_ADDRESS_DELETE = 'customerAddressDelete ' ;
70
+
71
+ /**
72
+ * @var CustomerRepositoryInterface
73
+ */
74
+ private $ customerRepository ;
75
+
76
+ /**
77
+ * @var AddressRepositoryInterface
78
+ */
79
+ private $ addressRepositoryInterface ;
80
+
81
+ /**
82
+ * @var AddressInterfaceFactory
83
+ */
84
+ private $ addressInterfaceFactory ;
85
+
86
+ /**
87
+ * @var RegionInterfaceFactory
88
+ */
89
+ private $ regionInterfaceFactory ;
90
+
91
+ /**
92
+ * @var AttributeInterfaceFactory
93
+ */
94
+ private $ attributeInterfaceFactory ;
95
+
96
+ /**
97
+ * @var AddressExtensionInterfaceFactory
98
+ */
99
+ private $ addressExtensionInterfaceFactory ;
100
+
101
+ /**
102
+ * @var Config
103
+ */
104
+ private $ eavConfig ;
105
+
106
+ /**
107
+ * @var AddressDataProvider
108
+ */
109
+ private $ addressDataProvider ;
110
+
111
+ /**
112
+ * @param CustomerRepositoryInterface $customerRepository
113
+ * @param AddressRepositoryInterface $addressRepositoryInterface
114
+ * @param AddressInterfaceFactory $addressInterfaceFactory
115
+ * @param RegionInterfaceFactory $regionInterfaceFactory
116
+ * @param AttributeInterfaceFactory $attributeInterfaceFactory
117
+ * @param AddressExtensionInterfaceFactory $addressExtensionInterfaceFactory
118
+ * @param Config $eavConfig
119
+ * @param AddressDataProvider $addressDataProvider
120
+ */
121
+ public function __construct (
122
+ CustomerRepositoryInterface $ customerRepository ,
123
+ AddressRepositoryInterface $ addressRepositoryInterface ,
124
+ AddressInterfaceFactory $ addressInterfaceFactory ,
125
+ RegionInterfaceFactory $ regionInterfaceFactory ,
126
+ AttributeInterfaceFactory $ attributeInterfaceFactory ,
127
+ AddressExtensionInterfaceFactory $ addressExtensionInterfaceFactory ,
128
+ Config $ eavConfig ,
129
+ AddressDataProvider $ addressDataProvider
130
+ ) {
131
+ $ this ->customerRepository = $ customerRepository ;
132
+ $ this ->addressRepositoryInterface = $ addressRepositoryInterface ;
133
+ $ this ->addressInterfaceFactory = $ addressInterfaceFactory ;
134
+ $ this ->regionInterfaceFactory = $ regionInterfaceFactory ;
135
+ $ this ->attributeInterfaceFactory = $ attributeInterfaceFactory ;
136
+ $ this ->addressExtensionInterfaceFactory = $ addressExtensionInterfaceFactory ;
137
+ $ this ->eavConfig = $ eavConfig ;
138
+ $ this ->addressDataProvider = $ addressDataProvider ;
139
+ }
140
+
141
+ /**
142
+ * {@inheritdoc}
143
+ */
144
+ public function resolve (
145
+ Field $ field ,
146
+ $ context ,
147
+ ResolveInfo $ info ,
148
+ array $ value = null ,
149
+ array $ args = null
150
+ ) {
151
+ /** @var ContextInterface $context */
152
+ if ((!$ context ->getUserId ()) || $ context ->getUserType () == UserContextInterface::USER_TYPE_GUEST ) {
153
+ throw new GraphQlAuthorizationException (
154
+ __ (
155
+ 'Current customer does not have access to the resource "%1" ' ,
156
+ [\Magento \Customer \Model \Customer::ENTITY ]
157
+ )
158
+ );
159
+ }
160
+ /** @var \Magento\Customer\Api\Data\CustomerInterface $customer */
161
+ $ customer = $ this ->customerRepository ->getById ($ context ->getUserId ());
162
+ switch ($ field ->getName ()) {
163
+ case self ::MUTATION_ADDRESS_CREATE :
164
+ return $ this ->addressDataProvider ->processCustomerAddress (
165
+ $ this ->processCustomerAddressCreate ($ customer , $ args ['input ' ])
166
+ );
167
+ case self ::MUTATION_ADDRESS_UPDATE :
168
+ return $ this ->addressDataProvider ->processCustomerAddress (
169
+ $ this ->processCustomerAddressUpdate ($ customer , $ args ['id ' ], $ args ['input ' ])
170
+ );
171
+ case self ::MUTATION_ADDRESS_DELETE :
172
+ return $ this ->processCustomerAddressDelete ($ customer , $ args ['id ' ]);
173
+ default :
174
+ return [];
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Get input address attribute errors
180
+ * @param $addressInput
181
+ * @return bool|string
182
+ */
183
+ private function getAddressInputError ($ addressInput )
184
+ {
185
+ foreach (self ::ADDRESS_ATTRIBUTES as $ attribute ) {
186
+ if ($ this ->isAttributeRequired ($ attribute ) && !isset ($ addressInput [$ attribute ])) {
187
+ return $ attribute ;
188
+ }
189
+ }
190
+ return false ;
191
+ }
192
+
193
+ /**
194
+ * Check if attribute is set as required
195
+ * @param $attributeName
196
+ * @return bool
197
+ */
198
+ private function isAttributeRequired ($ attributeName )
199
+ {
200
+ return $ this ->eavConfig ->getAttribute (
201
+ AddressMetadataManagementInterface::ENTITY_TYPE_ADDRESS ,
202
+ $ attributeName
203
+ )->getIsRequired ();
204
+ }
205
+
206
+ /**
207
+ * @param AddressInterface $address
208
+ * @param array $addressInput
209
+ * @return AddressInterface
210
+ */
211
+ private function fillAddress ($ address , $ addressInput )
212
+ {
213
+ if (isset ($ addressInput [AddressInterface::REGION ])) {
214
+ /** @var \Magento\Customer\Api\Data\RegionInterface $newRegion */
215
+ $ newRegion = $ this ->regionInterfaceFactory ->create ($ addressInput [AddressInterface::REGION ]);
216
+ $ address ->setRegion ($ newRegion );
217
+ }
218
+ if (isset ($ addressInput [AddressInterface::REGION_ID ])) {
219
+ $ address ->setRegionId ($ addressInput [AddressInterface::REGION_ID ]);
220
+ }
221
+ if (isset ($ addressInput [AddressInterface::COUNTRY_ID ])) {
222
+ $ address ->setCountryId ($ addressInput [AddressInterface::COUNTRY_ID ]);
223
+ }
224
+ if (isset ($ addressInput [AddressInterface::STREET ])) {
225
+ $ address ->setStreet ($ addressInput [AddressInterface::STREET ]);
226
+ }
227
+ if (isset ($ addressInput [AddressInterface::COMPANY ])) {
228
+ $ address ->setCompany ($ addressInput [AddressInterface::COMPANY ]);
229
+ }
230
+ if (isset ($ addressInput [AddressInterface::TELEPHONE ])) {
231
+ $ address ->setTelephone ($ addressInput [AddressInterface::TELEPHONE ]);
232
+ }
233
+ if (isset ($ addressInput [AddressInterface::FAX ])) {
234
+ $ address ->setFax ($ addressInput [AddressInterface::FAX ]);
235
+ }
236
+ if (isset ($ addressInput [AddressInterface::POSTCODE ])) {
237
+ $ address ->setPostcode ($ addressInput [AddressInterface::POSTCODE ]);
238
+ }
239
+ if (isset ($ addressInput [AddressInterface::CITY ])) {
240
+ $ address ->setCity ($ addressInput [AddressInterface::CITY ]);
241
+ }
242
+ if (isset ($ addressInput [AddressInterface::FIRSTNAME ])) {
243
+ $ address ->setFirstname ($ addressInput [AddressInterface::FIRSTNAME ]);
244
+ }
245
+ if (isset ($ addressInput [AddressInterface::LASTNAME ])) {
246
+ $ address ->setLastname ($ addressInput [AddressInterface::LASTNAME ]);
247
+ }
248
+ if (isset ($ addressInput [AddressInterface::MIDDLENAME ])) {
249
+ $ address ->setMiddlename ($ addressInput [AddressInterface::MIDDLENAME ]);
250
+ }
251
+ if (isset ($ addressInput [AddressInterface::PREFIX ])) {
252
+ $ address ->setPrefix ($ addressInput [AddressInterface::PREFIX ]);
253
+ }
254
+ if (isset ($ addressInput [AddressInterface::SUFFIX ])) {
255
+ $ address ->setSuffix ($ addressInput [AddressInterface::SUFFIX ]);
256
+ }
257
+ if (isset ($ addressInput [AddressInterface::VAT_ID ])) {
258
+ $ address ->setVatId ($ addressInput [AddressInterface::VAT_ID ]);
259
+ }
260
+ if (isset ($ addressInput [AddressInterface::DEFAULT_BILLING ])) {
261
+ $ address ->setIsDefaultBilling ($ addressInput [AddressInterface::DEFAULT_BILLING ]);
262
+ }
263
+ if (isset ($ addressInput [AddressInterface::DEFAULT_SHIPPING ])) {
264
+ $ address ->setIsDefaultShipping ($ addressInput [AddressInterface::DEFAULT_SHIPPING ]);
265
+ }
266
+ if (isset ($ addressInput [AddressInterface::DEFAULT_SHIPPING ])) {
267
+ $ address ->setIsDefaultShipping ($ addressInput [AddressInterface::DEFAULT_SHIPPING ]);
268
+ }
269
+ if (isset ($ addressInput [self ::CUSTOM_ATTRIBUTE_KEY ])) {
270
+ foreach ($ addressInput [self ::CUSTOM_ATTRIBUTE_KEY ] as $ attribute ) {
271
+ $ address ->setCustomAttribute ($ attribute ['attribute_code ' ], $ attribute ['value ' ]);
272
+ }
273
+ }
274
+ if (isset ($ addressInput [self ::EXTENSION_ATTRIBUTE_KEY ])) {
275
+ $ extensionAttributes = $ address ->getExtensionAttributes ();
276
+ if (!$ extensionAttributes ) {
277
+ /** @var \Magento\Customer\Api\Data\AddressExtensionInterface $newExtensionAttribute */
278
+ $ extensionAttributes = $ this ->addressExtensionInterfaceFactory ->create ();
279
+ }
280
+ foreach ($ addressInput [self ::EXTENSION_ATTRIBUTE_KEY ] as $ attribute ) {
281
+ $ extensionAttributes ->setData ($ attribute ['attribute_code ' ], $ attribute ['value ' ]);
282
+ }
283
+ $ address ->setExtensionAttributes ($ extensionAttributes );
284
+ }
285
+ return $ address ;
286
+ }
287
+
288
+ /**
289
+ * Process customer address create
290
+ * @param CustomerInterface $customer
291
+ * @param array $addressInput
292
+ * @return AddressInterface
293
+ * @throws GraphQlInputException
294
+ */
295
+ private function processCustomerAddressCreate ($ customer , $ addressInput )
296
+ {
297
+ $ errorInput = $ this ->getAddressInputError ($ addressInput );
298
+ if ($ errorInput ) {
299
+ throw new GraphQlInputException (__ ('Required parameter %1 is missing ' , [$ errorInput ]));
300
+ }
301
+ /** @var AddressInterface $newAddress */
302
+ $ newAddress = $ this ->fillAddress (
303
+ $ this ->addressInterfaceFactory ->create (),
304
+ $ addressInput
305
+ );
306
+ $ newAddress ->setCustomerId ($ customer ->getId ());
307
+ return $ this ->addressRepositoryInterface ->save ($ newAddress );
308
+ }
309
+
310
+ /**
311
+ * Process customer address update
312
+ * @param CustomerInterface $customer
313
+ * @param int $addressId
314
+ * @param array $addressInput
315
+ * @return AddressInterface
316
+ * @throws GraphQlAuthorizationException
317
+ * @throws GraphQlNoSuchEntityException
318
+ */
319
+ private function processCustomerAddressUpdate ($ customer , $ addressId , $ addressInput )
320
+ {
321
+ try {
322
+ /** @var AddressInterface $address */
323
+ $ address = $ this ->addressRepositoryInterface ->getById ($ addressId );
324
+ } catch (NoSuchEntityException $ exception ) {
325
+ throw new GraphQlNoSuchEntityException (
326
+ __ ('Address id %1 does not exist. ' , [$ addressId ])
327
+ );
328
+ }
329
+ if ($ address ->getCustomerId () != $ customer ->getId ()) {
330
+ throw new GraphQlAuthorizationException (
331
+ __ ('Current customer does not have permission to update address id %1 ' , [$ addressId ])
332
+ );
333
+ }
334
+ return $ this ->addressRepositoryInterface ->save (
335
+ $ this ->fillAddress ($ address , $ addressInput )
336
+ );
337
+ }
338
+
339
+ /**
340
+ * Process customer address delete
341
+ * @param CustomerInterface $customer
342
+ * @param int $addressId
343
+ * @return bool
344
+ * @throws GraphQlAuthorizationException
345
+ * @throws GraphQlNoSuchEntityException
346
+ */
347
+ private function processCustomerAddressDelete ($ customer , $ addressId )
348
+ {
349
+ try {
350
+ /** @var AddressInterface $address */
351
+ $ address = $ this ->addressRepositoryInterface ->getById ($ addressId );
352
+ } catch (NoSuchEntityException $ exception ) {
353
+ throw new GraphQlNoSuchEntityException (
354
+ __ ('Address id %1 does not exist. ' , [$ addressId ])
355
+ );
356
+ }
357
+ if ($ address ->getCustomerId () != $ customer ->getId ()) {
358
+ throw new GraphQlAuthorizationException (
359
+ __ ('Current customer does not have permission to delete address id %1 ' , [$ addressId ])
360
+ );
361
+ }
362
+ if ($ address ->isDefaultBilling ()) {
363
+ throw new GraphQlAuthorizationException (
364
+ __ ('Customer Address %1 is set as default billing address and can not be deleted ' , [$ addressId ])
365
+ );
366
+ }
367
+ if ($ address ->isDefaultShipping ()) {
368
+ throw new GraphQlAuthorizationException (
369
+ __ ('Customer Address %1 is set as default shipping address and can not be deleted ' , [$ addressId ])
370
+ );
371
+ }
372
+ return $ this ->addressRepositoryInterface ->delete ($ address );
373
+ }
374
+ }
0 commit comments