Completed
Push — master ( 0b205b...bde6a0 )
by
unknown
10:16
created

CartStrategy::findExistingEntity()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 26
rs 8.8571
c 1
b 0
f 0
cc 3
eloc 13
nc 3
nop 2
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
9
use OroCRM\Bundle\MagentoBundle\Entity\Cart;
10
use OroCRM\Bundle\MagentoBundle\Entity\CartAddress;
11
use OroCRM\Bundle\MagentoBundle\Entity\CartStatus;
12
use OroCRM\Bundle\MagentoBundle\Entity\MagentoSoapTransport;
13
use OroCRM\Bundle\MagentoBundle\ImportExport\Converter\GuestCustomerDataConverter;
14
use OroCRM\Bundle\MagentoBundle\Provider\Reader\ContextCustomerReader;
15
16
class CartStrategy extends AbstractImportStrategy
17
{
18
    /**
19
     * @var Cart
20
     */
21
    protected $existingEntity;
22
23
    /**
24
     * @var array
25
     */
26
    protected $existingCartItems;
27
28
    /**
29
     * @param Cart $entity
30
     *
31
     * {@inheritdoc}
32
     */
33
    protected function beforeProcessEntity($entity)
34
    {
35
        $this->existingEntity = $this->databaseHelper->findOneByIdentity($entity);
36
        if ($this->existingEntity) {
37
            $this->existingCartItems = $this->existingEntity->getCartItems()->toArray();
38
        } else {
39
            $this->existingEntity = $entity;
40
        }
41
42
        return parent::beforeProcessEntity($entity);
43
    }
44
45
    /**
46
     * @param Cart $entity
47
     *
48
     * {@inheritdoc}
49
     */
50 View Code Duplication
    public function process($entity)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
51
    {
52
        if (!$this->isProcessingAllowed($entity)) {
53
            $this->appendDataToContext(
54
                CartWithExistingCustomerStrategy::CONTEXT_CART_POST_PROCESS,
55
                $this->context->getValue('itemData')
56
            );
57
58
            return null;
59
        }
60
61
        return parent::process($entity);
62
    }
63
64
    /**
65
     * @param Cart $cart
66
     * @return bool
67
     */
68
    protected function isProcessingAllowed(Cart $cart)
69
    {
70
        $isProcessingAllowed = true;
71
72
        if ($cart->getCustomer()) {
73
            $customer = $this->findExistingEntity($cart->getCustomer());
74
75
            $customerOriginId = $cart->getCustomer()->getOriginId();
76
            if (!$customer && $customerOriginId) {
77
                $this->appendDataToContext(ContextCustomerReader::CONTEXT_POST_PROCESS_CUSTOMERS, $customerOriginId);
78
79
                $isProcessingAllowed = false;
80
            }
81
82
            if (!$customer && $cart->getIsGuest()) {
83
                /** @var MagentoSoapTransport $transport */
84
                $channel = $this->databaseHelper->findOneByIdentity($cart->getChannel());
85
                $transport = $channel->getTransport();
86
                if ($transport->getGuestCustomerSync()) {
87
                    $this->appendDataToContext(
88
                        'postProcessGuestCustomers',
89
                        GuestCustomerDataConverter::extractCustomersValues((array)$this->context->getValue('itemData'))
90
                    );
91
92
                    $isProcessingAllowed = false;
93
                }
94
            }
95
        }
96
97
        return $isProcessingAllowed;
98
    }
99
100
    /**
101
     * @param Cart $entity
102
     *
103
     * {@inheritdoc}
104
     */
105
    protected function afterProcessEntity($entity)
106
    {
107
        if ($this->existingEntity->getStatus()->getName() === CartStatus::STATUS_OPEN) {
108
            $this->updateRemovedCartItems($entity);
109
        }
110
111
        if (!$this->hasContactInfo($entity)) {
112
            return null;
113
        }
114
115
        $this
116
            ->updateCustomer($entity)
117
            ->updateAddresses($entity)
118
            ->updateCartItems($entity)
119
            ->updateCartStatus($entity);
120
121
        $now = new \DateTime('now', new \DateTimeZone('UTC'));
122
        if (!$entity->getImportedAt()) {
123
            $entity->setImportedAt($now);
124
        }
125
        $entity->setSyncedAt($now);
126
127
        $this->existingEntity = null;
128
        $this->existingCartItems = null;
0 ignored issues
show
Documentation Bug introduced by
It seems like null of type null is incompatible with the declared type array of property $existingCartItems.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
129
130
        return parent::afterProcessEntity($entity);
131
    }
132
133
    /**
134
     * Update removed cart items - set `removed` field to true if cart item was removed from a cart
135
     *
136
     * @param Cart $entity
137
     */
138
    protected function updateRemovedCartItems(Cart $entity)
139
    {
140
        if ((int)$entity->getItemsQty() === 0) {
141 View Code Duplication
            foreach ($entity->getCartItems() as $cartItem) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
142
                if (!$cartItem->isRemoved()) {
143
                    $cartItem->setUpdatedAt(new \DateTime('now'), new \DateTimeZone('UTC'));
144
                    $cartItem->setRemoved(true);
145
                }
146
            }
147
        } elseif ($this->existingCartItems) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->existingCartItems of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
148
            $existingCartItems = new ArrayCollection($this->existingCartItems);
149
            $newCartItems = $entity->getCartItems();
150
151 View Code Duplication
            foreach ($existingCartItems as $existingCartItem) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
152
                if (!$newCartItems->contains($existingCartItem)) {
153
                    if (!$existingCartItem->isRemoved()) {
154
                        $existingCartItem->setUpdatedAt(new \DateTime('now'), new \DateTimeZone('UTC'));
155
                        $existingCartItem->setRemoved(true);
156
                    }
157
                }
158
            }
159
        }
160
    }
161
162
    /**
163
     * Update Customer email
164
     *
165
     * @param Cart $cart
166
     *
167
     * @return CartStrategy
168
     */
169
    protected function updateCustomer(Cart $cart)
170
    {
171
        $customer = $cart->getCustomer();
172
        if ($customer && !$customer->getEmail()) {
173
            $customer->setEmail($cart->getEmail());
174
        }
175
176
        return $this;
177
    }
178
179
    /**
180
     * @param Cart $cart
181
     *
182
     * @return CartStrategy
183
     */
184
    protected function updateCartItems(Cart $cart)
185
    {
186
        foreach ($cart->getCartItems() as $cartItem) {
187
            $cartItem->setOwner($cart->getOrganization());
188
            $cartItem->setCart($cart);
189
        }
190
191
        return $this;
192
    }
193
194
    /**
195
     * @param Cart $entity
196
     *
197
     * @return CartStrategy
198
     */
199
    protected function updateAddresses(Cart $entity)
200
    {
201
        $addresses = ['shippingAddress', 'billingAddress'];
202
203
        foreach ($addresses as $addressName) {
204
            /** @var CartAddress $address */
205
            $address = $this->getPropertyAccessor()->getValue($entity, $addressName);
206
207
            if (!$address) {
208
                continue;
209
            }
210
211
            // at this point imported address region have code equal to region_id in magento db field
212
            $mageRegionId = $address->getRegion() ? $address->getRegion()->getCode() : null;
213
            $this->addressHelper->updateAddressCountryRegion($address, $mageRegionId);
214
            if ($address->getCountry()) {
215
                $this->getPropertyAccessor()->setValue($entity, $addressName, $address);
216
            } else {
217
                $this->getPropertyAccessor()->setValue($entity, $addressName, null);
218
            }
219
        }
220
221
        return $this;
222
    }
223
224
    /**
225
     * @param Cart $entity
226
     * @return null
227
     */
228
    protected function hasContactInfo(Cart $entity)
229
    {
230
        $hasContactInfo = ($entity->getBillingAddress() && $entity->getBillingAddress()->getPhone())
231
            || $entity->getEmail();
232
233
        if (!$hasContactInfo) {
234
            $this->context->incrementErrorEntriesCount();
235
            $this->logger->debug(
236
                sprintf('Cart ID: %d was skipped because lack of contact info', $entity->getOriginId())
237
            );
238
239
            return false;
240
        }
241
242
        return true;
243
    }
244
245
    /**
246
     * Update cart status
247
     *
248
     * @param Cart $cart
249
     *
250
     * @return CartStrategy
251
     */
252
    protected function updateCartStatus(Cart $cart)
253
    {
254
        // allow to modify status only for "open" carts
255
        // because magento can only expire cart, so for different statuses this useless
256
        if ($this->existingEntity->getStatus()->getName() !== CartStatus::STATUS_OPEN) {
257
            $status = $this->existingEntity->getStatus();
258
        } else {
259
            $status = $cart->getStatus();
260
        }
261
262
        $cart->setStatus($status);
263
264
        return $this;
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    protected function findExistingEntity($entity, array $searchContext = [])
271
    {
272
        $existingEntity = null;
273
274
        if ($entity instanceof Region) {
275
            /** @var \OroCRM\Bundle\MagentoBundle\Entity\Region $magentoRegion */
276
            $magentoRegion = $this->databaseHelper->findOneBy(
277
                'OroCRM\Bundle\MagentoBundle\Entity\Region',
278
                [
279
                    'regionId' => $entity->getCode()
280
                ]
281
            );
282
            if ($magentoRegion) {
283
                $existingEntity = $this->databaseHelper->findOneBy(
284
                    'Oro\Bundle\AddressBundle\Entity\Region',
285
                    [
286
                        'combinedCode' => $magentoRegion->getCombinedCode()
287
                    ]
288
                );
289
            }
290
        } else {
291
            $existingEntity = parent::findExistingEntity($entity, $searchContext);
292
        }
293
294
        return $existingEntity;
295
    }
296
}
297