1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace OroCRM\Bundle\MagentoBundle\ImportExport\Strategy; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\Collections\ArrayCollection; |
6
|
|
|
|
7
|
|
|
use Oro\Bundle\AddressBundle\Entity\Region; |
8
|
|
|
use Oro\Bundle\IntegrationBundle\Entity\Channel; |
9
|
|
|
|
10
|
|
|
use OroCRM\Bundle\MagentoBundle\Entity\Cart; |
11
|
|
|
use OroCRM\Bundle\MagentoBundle\Entity\CartAddress; |
12
|
|
|
use OroCRM\Bundle\MagentoBundle\Entity\CartStatus; |
13
|
|
|
use OroCRM\Bundle\MagentoBundle\Entity\Customer; |
14
|
|
|
use OroCRM\Bundle\MagentoBundle\Entity\MagentoSoapTransport; |
15
|
|
|
use OroCRM\Bundle\MagentoBundle\ImportExport\Converter\GuestCustomerDataConverter; |
16
|
|
|
use OroCRM\Bundle\MagentoBundle\Provider\Reader\ContextCustomerReader; |
17
|
|
|
|
18
|
|
|
class CartStrategy extends AbstractImportStrategy |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* @var Cart |
22
|
|
|
*/ |
23
|
|
|
protected $existingEntity; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var array |
27
|
|
|
*/ |
28
|
|
|
protected $existingCartItems; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @param Cart $entity |
32
|
|
|
* |
33
|
|
|
* {@inheritdoc} |
34
|
|
|
*/ |
35
|
|
|
protected function beforeProcessEntity($entity) |
36
|
|
|
{ |
37
|
|
|
$this->existingEntity = $this->databaseHelper->findOneByIdentity($entity); |
38
|
|
|
if ($this->existingEntity) { |
39
|
|
|
$this->existingCartItems = $this->existingEntity->getCartItems()->toArray(); |
40
|
|
|
} else { |
41
|
|
|
$this->existingEntity = $entity; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
return parent::beforeProcessEntity($entity); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @param Cart $entity |
49
|
|
|
* |
50
|
|
|
* {@inheritdoc} |
51
|
|
|
*/ |
52
|
|
View Code Duplication |
public function process($entity) |
|
|
|
|
53
|
|
|
{ |
54
|
|
|
if (!$this->isProcessingAllowed($entity)) { |
55
|
|
|
$this->appendDataToContext( |
56
|
|
|
CartWithExistingCustomerStrategy::CONTEXT_CART_POST_PROCESS, |
57
|
|
|
$this->context->getValue('itemData') |
58
|
|
|
); |
59
|
|
|
|
60
|
|
|
return null; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
return parent::process($entity); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param Cart $cart |
68
|
|
|
* @return bool |
69
|
|
|
*/ |
70
|
|
|
protected function isProcessingAllowed(Cart $cart) |
71
|
|
|
{ |
72
|
|
|
$isProcessingAllowed = true; |
73
|
|
|
|
74
|
|
|
if ($cart->getCustomer()) { |
75
|
|
|
$customer = $this->findExistingCustomer($cart); |
76
|
|
|
$customerOriginId = $cart->getCustomer()->getOriginId(); |
77
|
|
|
if (!$customer && $customerOriginId) { |
78
|
|
|
$this->appendDataToContext(ContextCustomerReader::CONTEXT_POST_PROCESS_CUSTOMERS, $customerOriginId); |
79
|
|
|
|
80
|
|
|
$isProcessingAllowed = false; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* If registered customer add items to cart in Magento |
85
|
|
|
* but after customer was deleted in Magento before customer and cart were synced |
86
|
|
|
* Cart will not have connection to the customer |
87
|
|
|
* Customer for such Carts should be processed as guest if Guest Customer synchronization is allowed |
88
|
|
|
*/ |
89
|
|
|
if (!$customer && !$customerOriginId) { |
90
|
|
|
/** @var Channel $channel */ |
91
|
|
|
$channel = $this->databaseHelper->findOneByIdentity($cart->getChannel()); |
92
|
|
|
/** @var MagentoSoapTransport $transport */ |
93
|
|
|
$transport = $channel->getTransport(); |
94
|
|
|
if ($transport->getGuestCustomerSync()) { |
95
|
|
|
$this->appendDataToContext( |
96
|
|
|
'postProcessGuestCustomers', |
97
|
|
|
GuestCustomerDataConverter::extractCustomersValues((array)$this->context->getValue('itemData')) |
98
|
|
|
); |
99
|
|
|
|
100
|
|
|
$isProcessingAllowed = false; |
101
|
|
|
} |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
return $isProcessingAllowed; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* Get existing registered customer or existing guest customer |
110
|
|
|
* If customer not found by Identifier |
111
|
|
|
* find existing customer using entity data for entities containing customer like Order and Cart |
112
|
|
|
* |
113
|
|
|
* @param Cart $entity |
114
|
|
|
* |
115
|
|
|
* @return null|Customer |
116
|
|
|
*/ |
117
|
|
View Code Duplication |
protected function findExistingCustomer($entity) |
|
|
|
|
118
|
|
|
{ |
119
|
|
|
$existingEntity = null; |
120
|
|
|
$customer = $entity->getCustomer(); |
121
|
|
|
|
122
|
|
|
if ($customer->getId() || $customer->getOriginId()) { |
123
|
|
|
$existingEntity = parent::findExistingEntity($customer); |
|
|
|
|
124
|
|
|
} |
125
|
|
|
if (!$existingEntity) { |
126
|
|
|
$existingEntity = $this->findExistingCustomerByContext($entity); |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
return $existingEntity; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param Cart $entity |
134
|
|
|
* |
135
|
|
|
* {@inheritdoc} |
136
|
|
|
*/ |
137
|
|
|
protected function afterProcessEntity($entity) |
138
|
|
|
{ |
139
|
|
|
if ($this->existingEntity->getStatus()->getName() === CartStatus::STATUS_OPEN) { |
140
|
|
|
$this->updateRemovedCartItems($entity); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
if (!$this->hasContactInfo($entity)) { |
144
|
|
|
return null; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
$this |
148
|
|
|
->updateCustomer($entity) |
149
|
|
|
->updateAddresses($entity) |
150
|
|
|
->updateCartItems($entity) |
151
|
|
|
->updateCartStatus($entity); |
152
|
|
|
|
153
|
|
|
$now = new \DateTime('now', new \DateTimeZone('UTC')); |
154
|
|
|
if (!$entity->getImportedAt()) { |
155
|
|
|
$entity->setImportedAt($now); |
156
|
|
|
} |
157
|
|
|
$entity->setSyncedAt($now); |
158
|
|
|
|
159
|
|
|
$this->existingEntity = null; |
160
|
|
|
$this->existingCartItems = null; |
|
|
|
|
161
|
|
|
|
162
|
|
|
return parent::afterProcessEntity($entity); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Update removed cart items - set `removed` field to true if cart item was removed from a cart |
167
|
|
|
* |
168
|
|
|
* @param Cart $entity |
169
|
|
|
*/ |
170
|
|
|
protected function updateRemovedCartItems(Cart $entity) |
171
|
|
|
{ |
172
|
|
|
if ((int)$entity->getItemsQty() === 0) { |
173
|
|
View Code Duplication |
foreach ($entity->getCartItems() as $cartItem) { |
|
|
|
|
174
|
|
|
if (!$cartItem->isRemoved()) { |
175
|
|
|
$cartItem->setUpdatedAt(new \DateTime('now', new \DateTimeZone('UTC'))); |
176
|
|
|
$cartItem->setRemoved(true); |
177
|
|
|
} |
178
|
|
|
} |
179
|
|
|
} elseif ($this->existingCartItems) { |
|
|
|
|
180
|
|
|
$existingCartItems = new ArrayCollection($this->existingCartItems); |
181
|
|
|
$newCartItems = $entity->getCartItems(); |
182
|
|
|
|
183
|
|
View Code Duplication |
foreach ($existingCartItems as $existingCartItem) { |
|
|
|
|
184
|
|
|
if (!$newCartItems->contains($existingCartItem)) { |
185
|
|
|
if (!$existingCartItem->isRemoved()) { |
186
|
|
|
$existingCartItem->setUpdatedAt(new \DateTime('now', new \DateTimeZone('UTC'))); |
187
|
|
|
$existingCartItem->setRemoved(true); |
188
|
|
|
} |
189
|
|
|
} |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* Update Customer email |
196
|
|
|
* |
197
|
|
|
* @param Cart $cart |
198
|
|
|
* |
199
|
|
|
* @return CartStrategy |
200
|
|
|
*/ |
201
|
|
|
protected function updateCustomer(Cart $cart) |
202
|
|
|
{ |
203
|
|
|
$customer = $cart->getCustomer(); |
204
|
|
|
if ($customer && !$customer->getEmail()) { |
205
|
|
|
$customer->setEmail($cart->getEmail()); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
return $this; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @param Cart $cart |
213
|
|
|
* |
214
|
|
|
* @return CartStrategy |
215
|
|
|
*/ |
216
|
|
|
protected function updateCartItems(Cart $cart) |
217
|
|
|
{ |
218
|
|
|
foreach ($cart->getCartItems() as $cartItem) { |
219
|
|
|
$cartItem->setOwner($cart->getOrganization()); |
220
|
|
|
$cartItem->setCart($cart); |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
return $this; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @param Cart $entity |
228
|
|
|
* |
229
|
|
|
* @return CartStrategy |
230
|
|
|
*/ |
231
|
|
|
protected function updateAddresses(Cart $entity) |
232
|
|
|
{ |
233
|
|
|
$addresses = ['shippingAddress', 'billingAddress']; |
234
|
|
|
|
235
|
|
|
foreach ($addresses as $addressName) { |
236
|
|
|
/** @var CartAddress $address */ |
237
|
|
|
$address = $this->getPropertyAccessor()->getValue($entity, $addressName); |
238
|
|
|
|
239
|
|
|
if (!$address) { |
240
|
|
|
continue; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
// at this point imported address region have code equal to region_id in magento db field |
244
|
|
|
$mageRegionId = $address->getRegion() ? $address->getRegion()->getCode() : null; |
245
|
|
|
$this->addressHelper->updateAddressCountryRegion($address, $mageRegionId); |
246
|
|
|
if ($address->getCountry()) { |
247
|
|
|
$this->getPropertyAccessor()->setValue($entity, $addressName, $address); |
248
|
|
|
} else { |
249
|
|
|
$this->getPropertyAccessor()->setValue($entity, $addressName, null); |
250
|
|
|
} |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
return $this; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* @param Cart $entity |
258
|
|
|
* @return null |
259
|
|
|
*/ |
260
|
|
|
protected function hasContactInfo(Cart $entity) |
261
|
|
|
{ |
262
|
|
|
$hasContactInfo = ($entity->getBillingAddress() && $entity->getBillingAddress()->getPhone()) |
263
|
|
|
|| $entity->getEmail(); |
264
|
|
|
|
265
|
|
|
if (!$hasContactInfo) { |
266
|
|
|
$this->context->incrementErrorEntriesCount(); |
267
|
|
|
$this->logger->debug( |
268
|
|
|
sprintf('Cart ID: %d was skipped because lack of contact info', $entity->getOriginId()) |
269
|
|
|
); |
270
|
|
|
|
271
|
|
|
return false; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
return true; |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
/** |
278
|
|
|
* Update cart status |
279
|
|
|
* |
280
|
|
|
* @param Cart $cart |
281
|
|
|
* |
282
|
|
|
* @return CartStrategy |
283
|
|
|
*/ |
284
|
|
|
protected function updateCartStatus(Cart $cart) |
285
|
|
|
{ |
286
|
|
|
// allow to modify status only for "open" carts |
287
|
|
|
// because magento can only expire cart, so for different statuses this useless |
288
|
|
|
if ($this->existingEntity->getStatus()->getName() !== CartStatus::STATUS_OPEN) { |
289
|
|
|
$status = $this->existingEntity->getStatus(); |
290
|
|
|
} else { |
291
|
|
|
$status = $cart->getStatus(); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
$cart->setStatus($status); |
295
|
|
|
|
296
|
|
|
return $this; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* {@inheritdoc} |
301
|
|
|
*/ |
302
|
|
|
protected function findExistingEntity($entity, array $searchContext = []) |
303
|
|
|
{ |
304
|
|
|
$existingEntity = null; |
|
|
|
|
305
|
|
|
|
306
|
|
|
if ($entity instanceof Region) { |
307
|
|
|
/** @var \OroCRM\Bundle\MagentoBundle\Entity\Region $existingEntity */ |
308
|
|
|
$existingEntity = $this->findRegionEntity($entity); |
309
|
|
View Code Duplication |
} elseif ($entity instanceof Customer && !$entity->getOriginId() && $this->existingEntity) { |
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Get existing customer entity |
312
|
|
|
* As guest customer entity not exist in Magento as separate entity and saved in order |
313
|
|
|
* find guest by customer email |
314
|
|
|
*/ |
315
|
|
|
$existingEntity = $this->findExistingCustomerByContext($this->existingEntity); |
316
|
|
|
} else { |
317
|
|
|
$existingEntity = parent::findExistingEntity($entity, $searchContext); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
return $existingEntity; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Add cart customer email to customer search context |
325
|
|
|
* |
326
|
|
|
* {@inheritdoc} |
327
|
|
|
*/ |
328
|
|
|
protected function getEntityCustomerSearchContext($cart) |
329
|
|
|
{ |
330
|
|
|
/** @var Cart $cart */ |
331
|
|
|
$searchContext = parent::getEntityCustomerSearchContext($cart); |
332
|
|
|
$searchContext['email'] = $cart->getEmail(); |
333
|
|
|
|
334
|
|
|
return $searchContext; |
|
|
|
|
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.