Completed
Pull Request — master (#480)
by Sebastian
07:09
created

ProductFromShop::reserve()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
/**
3
 * (c) shopware AG <[email protected]>
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 */
7
8
namespace ShopwarePlugins\Connect\Components;
9
10
use Enlight_Event_EventManager;
11
12
use Shopware\Connect\Gateway;
13
use Shopware\Connect\ProductFromShop as ProductFromShopBase;
14
use Shopware\Connect\Struct\Order;
15
use Shopware\Connect\Struct\Product;
16
use Shopware\Connect\Struct\Address as ConnectAddress;
17
use Shopware\Connect\Struct\Change\FromShop\Availability;
18
use Shopware\Connect\Struct\Change\FromShop\Insert;
19
use Shopware\Connect\Struct\Change\FromShop\Update;
20
use Shopware\Connect\Struct\PaymentStatus;
21
use Shopware\Connect\Struct\Shipping;
22
23
use Shopware\Models\Shop\Shop;
24
use Shopware\Models\Order\Order as ShopwareOrder;
25
use Shopware\Models\Customer\Address as ShopwareAddress;
26
use Shopware\Models\Dispatch\Dispatch;
27
use Shopware\Models\Order as OrderModel;
28
use Shopware\Models\Attribute\OrderDetail as OrderDetailAttributeModel;
29
use Shopware\Models\Customer as CustomerModel;
30
31
use Shopware\Components\Model\ModelManager;
32
use Shopware\Components\Random;
33
34
use ShopwarePlugins\Connect\Components\ProductStream\ProductStreamService;
35
use Shopware\CustomModels\Connect\Attribute;
36
use Shopware\Connect\Struct\Message;
37
38
/**
39
 * The interface for products exported *to* connect *from* the local shop
40
 *
41
 * @category  Shopware
42
 * @package   Shopware\Plugins\SwagConnect
43
 */
44
class ProductFromShop implements ProductFromShopBase
45
{
46
    /**
47
     * @var Helper
48
     */
49
    private $helper;
50
51
    /**
52
     * @var ModelManager
53
     */
54
    private $manager;
55
56
    /**
57
     * @var \Shopware\Connect\Gateway
58
     */
59
    private $gateway;
60
61
    /**
62
     * @var Logger
63
     */
64
    private $logger;
65
66
    /**
67
     * @var Enlight_Event_EventManager
68
     */
69
    private $eventManager;
70
71
    /**
72
     * @param Helper $helper
73
     * @param ModelManager $manager
74
     * @param Gateway $gateway
75
     * @param Logger $logger
76
     * @param Enlight_Event_EventManager $eventManager
77
     */
78
    public function __construct(
79
        Helper $helper,
80
        ModelManager $manager,
81
        Gateway $gateway,
82
        Logger $logger,
83
        Enlight_Event_EventManager $eventManager
84
    ) {
85
        $this->helper = $helper;
86
        $this->manager = $manager;
87
        $this->gateway = $gateway;
88
        $this->logger = $logger;
89
        $this->eventManager = $eventManager;
90
    }
91
92
    /**
93
     * Get product data
94
     *
95
     * Get product data for all the source IDs specified in the given string
96
     * array.
97
     *
98
     * @param string[] $sourceIds
99
     * @return Product[]
100
     */
101
    public function getProducts(array $sourceIds)
102
    {
103
        return $this->helper->getLocalProduct($sourceIds);
104
    }
105
106
    /**
107
     * Get all IDs of all exported products
108
     *
109
     * @throws \BadMethodCallException
110
     * @return string[]
111
     */
112
    public function getExportedProductIDs()
113
    {
114
        throw new \BadMethodCallException('Not implemented');
115
    }
116
117
    /**
118
     * Reserve a product in shop for purchase
119
     *
120
     * @param Order $order
121
     * @throws \Exception Abort reservation by throwing an exception here.
122
     * @return void
123
     */
124
    public function reserve(Order $order)
125
    {
126
        $this->eventManager->notify(
127
            'Connect_Supplier_Reservation_Before',
128
            [
129
                'subject' => $this,
130
                'order' => $order
131
            ]
132
        );
133
    }
134
135
    /**
136
     * Create order in shopware
137
     * Wraps the actual order process into a transaction
138
     *
139
     *
140
     * @param Order $order
141
     * @throws \Exception Abort buy by throwing an exception,
142
     *                    but only in very important cases.
143
     *                    Do validation in {@see reserve} instead.
144
     * @return string
145
     */
146
    public function buy(Order $order)
147
    {
148
        $this->manager->beginTransaction();
149
        try {
150
            $order = $this->eventManager->filter('Connect_Components_ProductFromShop_Buy_OrderFilter', $order);
151
152
            $this->validateBilling($order->billingAddress);
153
            $orderNumber = $this->doBuy($order);
154
155
            $this->manager->commit();
156
        } catch (\Exception $e) {
157
            $this->manager->rollback();
158
            throw $e;
159
        }
160
161
        return $orderNumber;
162
    }
163
164
    /**
165
     * returns PaymentInformation for invoice
166
     * @return null|object|\Shopware\Models\Payment\Payment
167
     */
168
    private function getInvoicePayment()
169
    {
170
        $repository = $this->manager->getRepository('Shopware\Models\Payment\Payment');
171
        return $repository->findOneBy([
172
            'name' => 'invoice',
173
        ]);
174
    }
175
176
177
178
    /**
179
     * Actually creates the remote order in shopware.
180
     *
181
     * @param Order $order
182
     * @return string
183
     */
184
    public function doBuy(Order $order)
185
    {
186
        $this->manager->clear();
187
188
        $shop = $this->manager->find('Shopware\Models\Shop\Shop', 1);
189
        $shopwareOrder = $this->createAndReturnMinimalOrderInShopware($order, $shop);
190
191
        $this->fillShopwareOrderWithItems($shopwareOrder, $order);
192
193
        $customer = $this->prepareCustomerFromConnectOrder($order, $shop);
194
195
        $shopwareOrder->setCustomer($customer);
196
197
        $billing = new OrderModel\Billing();
198
        $billing->setCustomer($customer);
199
        $billing->fromArray($this->getAddressData(
200
                $order->billingAddress
201
        ));
202
        $shopwareOrder->setBilling($billing);
203
204
        $shipping = new OrderModel\Shipping();
205
        $shipping->setCustomer($customer);
206
        $shipping->fromArray($this->getAddressData(
207
            $order->deliveryAddress
208
        ));
209
        $shopwareOrder->setShipping($shipping);
210
211
        $shopwareOrder->calculateInvoiceAmount();
212
213
        $dispatchRepository = $this->manager->getRepository('Shopware\Models\Dispatch\Dispatch');
214
        $dispatch = $dispatchRepository->findOneBy([
215
            'name' => $order->shipping->service
216
        ]);
217
        if ($dispatch) {
218
            $shopwareOrder->setDispatch($dispatch);
219
        }
220
221
        $this->eventManager->notify(
222
            'Connect_Supplier_Buy_Before',
223
            [
224
                'subject' => $this,
225
                'order' => $order
226
            ]
227
        );
228
229
        $this->manager->flush();
230
231
        return $shopwareOrder->getNumber();
232
    }
233
234
    /**
235
     * @param Order $connectOrder
236
     * @param Shop $shop
237
     * @return ShopwareOrder
238
     * @throws \Doctrine\ORM\ORMException
239
     * @throws \Doctrine\ORM\OptimisticLockException
240
     * @throws \Doctrine\ORM\TransactionRequiredException
241
     * @throws \Zend_Db_Adapter_Exception
242
     */
243
    private function createAndReturnMinimalOrderInShopware(Order $connectOrder, Shop $shop)
244
    {
245
        $orderNumber = sprintf('SC-%s-%s',
246
            $connectOrder->orderShop,
247
            $connectOrder->localOrderId
248
        );
249
        $status = $this->manager->find('Shopware\Models\Order\Status', 0);
250
251
        // todo: Create the OrderModel without previous plain SQL
252
        //$model = new OrderModel\Order();
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
253
        $sql = 'INSERT INTO `s_order` (`ordernumber`, `cleared`) VALUES (?, 17);';
254
        Shopware()->Db()->query($sql, [$orderNumber]);
255
        $modelId = Shopware()->Db()->lastInsertId();
256
257
        /** @var $shopwareOrder \Shopware\Models\Order\Order */
258
        $shopwareOrder = $this->manager->find('Shopware\Models\Order\Order', $modelId);
259
260
        $attribute = new \Shopware\Models\Attribute\Order;
261
        $attribute->setConnectOrderId($connectOrder->localOrderId);
262
        $attribute->setConnectShopId($connectOrder->orderShop);
263
        $shopwareOrder->setAttribute($attribute);
264
265
        $shopwareOrder->fromArray([
266
            'number' => $orderNumber,
267
            'invoiceShipping' => $connectOrder->shipping->grossShippingCosts,
268
            'invoiceShippingNet' => $connectOrder->shipping->shippingCosts,
269
            'currencyFactor' => 1,
270
            'orderStatus' => $status,
271
            'shop' => $shop,
272
            'languageSubShop' => $shop,
273
            'payment' => $this->getInvoicePayment(),
274
            'currency' => 'EUR',
275
            'orderTime' => 'now'
276
        ]);
277
278
        return $shopwareOrder;
279
    }
280
281
    /**
282
     * iterates through order items and converts them to positions in shopware order
283
     * @param ShopwareOrder $shopwareOrder
284
     * @param Order $connectOrder
285
     * @throws \Doctrine\ORM\ORMException
286
     * @throws \Doctrine\ORM\OptimisticLockException
287
     * @throws \Doctrine\ORM\TransactionRequiredException
288
     */
289
    private function fillShopwareOrderWithItems(ShopwareOrder $shopwareOrder, Order $connectOrder)
290
    {
291
        $openDetailStatus = $this->manager->find('Shopware\Models\Order\DetailStatus', 0);
292
        $connectAttributeRepository = $this->manager->getRepository('Shopware\CustomModels\Connect\Attribute');
293
294
        $items = [];
295
        /** @var \Shopware\Connect\Struct\OrderItem $orderItem */
296
        foreach ($connectOrder->orderItems as $orderItem) {
297
            $product = $orderItem->product;
298
            /** @var \Shopware\CustomModels\Connect\Attribute $connectAttribute */
299
            //use null as shop id to fetch exported articles
300
            $connectAttribute = $connectAttributeRepository->findOneBy([
301
                'sourceId' => $product->sourceId,
302
                'shopId' => null,
303
            ]);
304
            if (!$connectAttribute) {
305
                $this->logger->write(
306
                    true,
307
                    sprintf('Detail with sourceId: %s does not exist', $product->sourceId),
308
                    null,
309
                    true
310
                );
311
                continue;
312
            }
313
314
            /** @var $detail \Shopware\Models\Article\Detail */
315
            $detail = $connectAttribute->getArticleDetail();
316
            /** @var $productModel \Shopware\Models\Article\Article */
317
            $productModel = $detail->getArticle();
318
            $item = new OrderModel\Detail();
319
            $item->fromArray([
320
                'articleId' => $productModel->getId(),
321
                'quantity' => $orderItem->count,
322
                'orderId' => $shopwareOrder->getId(),
323
                'number' => $shopwareOrder->getNumber(),
324
                'articleNumber' => $detail->getNumber(),
325
                'articleName' => $product->title,
326
                'price' => $this->calculatePrice($product),
327
                'taxRate' => $product->vat * 100,
328
                'status' => $openDetailStatus,
329
                'attribute' => new OrderDetailAttributeModel()
330
            ]);
331
            $items[] = $item;
332
        }
333
        $shopwareOrder->setDetails($items);
334
    }
335
336
    /**
337
     * Reads customer information from connectOrder and creates a new customer if it does not exists
338
     * @param Order $connectOrder
339
     * @param Shop $shop
340
     * @return CustomerModel\Customer
341
     */
342
    private function prepareCustomerFromConnectOrder(Order $connectOrder, Shop $shop)
343
    {
344
        $email = $connectOrder->billingAddress->email;
345
346
        $customerRepository = $this->manager->getRepository('Shopware\Models\Customer\Customer');
347
348
        /** @var CustomerModel\Customer $customer */
349
        $customer = $customerRepository->findOneBy([
350
            'email' => $email
351
        ]);
352
353
        if ($customer === null) {
354
            $password = Random::getAlphanumericString(30);
355
            $customer = new CustomerModel\Customer();
356
            $customer->fromArray([
357
                'active' => true,
358
                'email' => $email,
359
                'password' => $password,
360
                'accountMode' => 1,
361
                'shop' => $shop,
362
                'paymentId' => $this->getInvoicePayment()->getId(),
363
            ]);
364
            //we need to save the customer right now to receive a id
365
            $this->manager->persist($customer);
366
            $this->manager->flush($customer);
367
        }
368
369
        $billingAddress = $customer->getDefaultBillingAddress();
370
        if ($billingAddress === null) {
371
            $billingAddress = new ShopwareAddress();
372
        }
373
374
        $billingAddress->fromArray($this->getAddressData(
375
            $connectOrder->billingAddress
376
        ));
377
        $billingAddress->setCustomer($customer);
378
        $this->manager->persist($billingAddress);
379
380
        $customer->setDefaultBillingAddress($billingAddress);
381
382
        $this->manager->persist($customer);
383
384
        return $customer;
385
    }
386
387
    /**
388
     * Calculate the price (including VAT) that the from shop needs to pay.
389
     *
390
     * This is most likely NOT the price the customer itself has to pay.
391
     *
392
     * @return float
393
     */
394
    private function calculatePrice($product)
395
    {
396
        return $product->purchasePrice * ($product->vat + 1);
397
    }
398
399
    /**
400
     * @param ConnectAddress $address
401
     * @return array
402
     */
403
    private function getAddressData(ConnectAddress $address)
404
    {
405
        $repository = 'Shopware\Models\Country\Country';
406
        $repository = $this->manager->getRepository($repository);
407
        /** @var $country \Shopware\Models\Country\Country */
408
        $country = $repository->findOneBy([
409
            'iso3' => $address->country
410
        ]);
411
412
        return [
413
            'company' => $address->company ?: '',
414
            'department' => $address->department ?: '',
415
            'additionalAddressLine1' => $address->additionalAddressLine1 ?: '',
416
            'additionalAddressLine2' => $address->additionalAddressLine2 ?: '',
417
            'salutation' => 'mr',
418
            'lastName' => $address->surName,
419
            'firstName' => $address->firstName,
420
            'city' => $address->city,
421
            'zipCode' => $address->zip,
422
            'street' => $address->street,
423
            'streetNumber' => $address->streetNumber,
424
            'phone' => $address->phone,
425
            'country' => $country
426
        ];
427
    }
428
429
    public function updatePaymentStatus(PaymentStatus $status)
430
    {
431
        // $paymentStatus->localOrderId is actually ordernumber for this shop
432
        // e.g. BP-35-20002
433
        $repository = $this->manager->getRepository('Shopware\Models\Order\Order');
434
        $order = $repository->findOneBy(['number' => $status->localOrderId]);
435
436
        if ($order) {
437
            $paymentStatusRepository = $this->manager->getRepository('Shopware\Models\Order\Status');
438
            /** @var \Shopware\Models\Order\Status $orderPaymentStatus */
439
            $orderPaymentStatus = $paymentStatusRepository->findOneBy(
440
                ['name' => 'sc_' . $status->paymentStatus]
441
            );
442
443
            if ($orderPaymentStatus) {
444
                $order->setPaymentStatus($orderPaymentStatus);
445
446
                $this->eventManager->notify(
447
                    'Connect_Supplier_Update_PaymentStatus_Before',
448
                    [
449
                        'subject' => $this,
450
                        'paymentStatus' => $status,
451
                        'order' => $order
452
                    ]
453
                );
454
455
                $this->manager->persist($order);
456
                $this->manager->flush();
457
            } else {
458
                $this->logger->write(
459
                    true,
460
                    sprintf(
461
                        'Payment status "%s" not found',
462
                        $status->paymentStatus
463
                    ),
464
                    sprintf(
465
                        'Order with id "%s"',
466
                        $status->localOrderId
467
                    )
468
                );
469
            }
470
        } else {
471
            $this->logger->write(
472
                true,
473
                sprintf(
474
                    'Order with id "%s" not found',
475
                    $status->localOrderId
476
                ),
477
                serialize($status)
478
            );
479
        }
480
    }
481
482
    public function calculateShippingCosts(Order $order)
483
    {
484 View Code Duplication
        if (!$order->deliveryAddress) {
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...
485
            return new Shipping([
486
                'isShippable' => false,
487
                'messages' => [
488
                    new Message([
489
                        'message' => 'delivery_address_empty'
490
                    ])
491
                ]
492
            ]);
493
        }
494
495
        $countryIso3 = $order->deliveryAddress->country;
496
        $country = $this->manager->getRepository('Shopware\Models\Country\Country')->findOneBy(['iso3' => $countryIso3]);
497
498 View Code Duplication
        if (!$country) {
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...
499
            return new Shipping([
500
                'isShippable' => false,
501
                'messages' => [
502
                    new Message([
503
                        'message' => 'order_not_shippable_to_country',
504
                        'values' => [
505
                            'country' => $countryIso3,
506
                        ]
507
                    ])
508
                ]
509
            ]);
510
        }
511
512
        if (count($order->orderItems) == 0) {
513
            throw new \InvalidArgumentException(
514
                'ProductList is not allowed to be empty'
515
            );
516
        }
517
518
        /* @var \Shopware\Models\Shop\Shop $shop */
519
        $shop = $this->manager->getRepository('Shopware\Models\Shop\Shop')->getActiveDefault();
520 View Code Duplication
        if (!$shop) {
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...
521
            return new Shipping([
522
                'isShippable' => false,
523
                'messages' => [
524
                    new Message([
525
                        'message' => 'default_shop_not_found'
526
                    ])
527
                ]
528
            ]);
529
        }
530
        $shop->registerResources(Shopware()->Container()->get('bootstrap'));
531
532
        /** @var /Enlight_Components_Session_Namespace $session */
0 ignored issues
show
Documentation introduced by
The doc-type /Enlight_Components_Session_Namespace could not be parsed: Unknown type name "/Enlight_Components_Session_Namespace" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
533
        $session = Shopware()->Session();
534
        $sessionId = uniqid('connect_remote');
535
        $session->offsetSet('sSESSION_ID', $sessionId);
536
537
        $repository = $this->manager->getRepository('Shopware\CustomModels\Connect\Attribute');
538
        $products = [];
539
        /** @var \Shopware\Connect\Struct\OrderItem $orderItem */
540
        foreach ($order->orderItems as $orderItem) {
541
            $attributes = $repository->findBy(['sourceId' => [$orderItem->product->sourceId], 'shopId' => null]);
542
            if (count($attributes) === 0) {
543
                continue;
544
            }
545
546
            $products[] = [
547
                'ordernumber' => $attributes[0]->getArticleDetail()->getNumber(),
548
                'quantity' => $orderItem->count,
549
            ];
550
        }
551
552
        /** @var \Shopware\CustomModels\Connect\Attribute $attribute */
553
        foreach ($products as $product) {
554
            Shopware()->Modules()->Basket()->sAddArticle($product['ordernumber'], $product['quantity']);
555
        }
556
557
        $shippingMethods = Shopware()->Modules()->Admin()->sGetPremiumDispatches($country->getId());
558 View Code Duplication
        if (empty($shippingMethods)) {
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...
559
            return new Shipping([
560
                'isShippable' => false,
561
                'messages' => [
562
                    new Message([
563
                        'message' => 'order_not_shippable_to_country',
564
                        'values' => [
565
                            'country' => $countryIso3,
566
                        ]
567
                    ])
568
                ]
569
            ]);
570
        }
571
572
        $shippingMethod = reset($shippingMethods);
573
574
        /** @var Dispatch $shipping */
575
        $shipping = $this->manager->getRepository(Dispatch::class)->find($shippingMethod['id']);
576
577 View Code Duplication
        if (!$shipping) {
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...
578
            return new Shipping([
579
                'isShippable' => false,
580
                'messages' => [
581
                    new Message([
582
                        'message' => 'default_shipping_not_found'
583
                    ])
584
                ]
585
            ]);
586
        }
587
588
        $session->offsetSet('sDispatch', $shipping->getId());
589
590
        $result = Shopware()->Modules()->Admin()->sGetPremiumShippingcosts(['id' => $country->getId()]);
591 View Code Duplication
        if (!is_array($result)) {
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...
592
            return new Shipping([
593
                'isShippable' => false,
594
                'messages' => [
595
                    new Message([
596
                        'message' => 'checkout_not_possible'
597
                    ])
598
                ]
599
            ]);
600
        }
601
602
        $sql = 'DELETE FROM s_order_basket WHERE sessionID=?';
603
        Shopware()->Db()->executeQuery($sql, [
604
            $sessionId,
605
        ]);
606
607
        $shippingReturn = new Shipping([
608
            'shopId' => $this->gateway->getShopId(),
609
            'service' => $shipping->getName(),
610
            'shippingCosts' => floatval($result['netto']),
611
            'grossShippingCosts' => floatval($result['brutto']),
612
        ]);
613
614
        $this->eventManager->notify(
615
            'Connect_Supplier_Get_Shipping_After',
616
            [
617
                'subject' => $this,
618
                'shipping' => $shippingReturn,
619
                'order' => $order
620
            ]
621
        );
622
623
        return $shippingReturn;
624
    }
625
626
    /**
627
     * Perform sync changes to fromShop
628
     *
629
     * @param string $since
630
     * @param \Shopware\Connect\Struct\Change[] $changes
631
     * @return void
632
     */
633
    public function onPerformSync($since, array $changes)
634
    {
635
        $this->manager->getConnection()->beginTransaction();
636
637
        $statusSynced = Attribute::STATUS_SYNCED;
638
        $statusInsert = Attribute::STATUS_INSERT;
639
        $statusUpdate = Attribute::STATUS_UPDATE;
640
        $statusDelete = Attribute::STATUS_DELETE;
641
        try {
642
            if ($since) {
643
                $this->manager->getConnection()->executeQuery(
644
                    'UPDATE s_plugin_connect_items
645
                    SET export_status = ?
646
                    WHERE revision <= ?
647
                    AND ( export_status = ? OR export_status = ? )',
648
                    [$statusSynced, $since, $statusInsert, $statusUpdate]
649
                );
650
651
                $this->manager->getConnection()->executeQuery(
652
                    'UPDATE s_plugin_connect_items
653
                    SET export_status = ?
654
                    WHERE revision <= ?
655
                    AND export_status = ?',
656
                    [null, $since, $statusDelete]
657
                );
658
            } else {
659
                $this->manager->getConnection()->executeQuery(
660
                    'UPDATE s_plugin_connect_items
661
                    SET export_status = ?
662
                    WHERE revision IS NULL
663
                    AND ( export_status = ? OR export_status = ? )',
664
                    [$statusSynced, $statusInsert, $statusUpdate]
665
                );
666
667
                $this->manager->getConnection()->executeQuery(
668
                    'UPDATE s_plugin_connect_items
669
                    SET export_status = ?
670
                    WHERE revision IS NULL
671
                    AND export_status = ?',
672
                    [null, $statusDelete]
673
                );
674
            }
675
676
677
            /** @var \Shopware\Connect\Struct\Change $change */
678
            foreach ($changes as $change) {
679
                if (!$change instanceof Insert && !$change instanceof Update && !$change instanceof Availability) {
680
                    continue;
681
                }
682
683
                $this->manager->getConnection()->executeQuery(
684
                    'UPDATE s_plugin_connect_items
685
                    SET revision = ?
686
                    WHERE source_id = ? AND shop_id IS NULL',
687
                    [$change->revision, $change->sourceId]
688
                );
689
            }
690
691
            $this->manager->getConnection()->commit();
692
        } catch (\Exception $e) {
693
            $this->manager->getConnection()->rollBack();
694
        }
695
696
        try {
697
            $this->markStreamsAsSynced();
698
            $this->markStreamsAsNotExported();
699
        } catch (\Exception $e) {
700
            $this->logger->write(
701
                true,
702
                sprintf('Failed to mark streams as synced! Message: "%s". Trace: "%s"', $e->getMessage(), $e->getTraceAsString()),
703
                null
704
            );
705
        }
706
    }
707
708 View Code Duplication
    private function markStreamsAsNotExported()
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...
709
    {
710
        $streamIds = $this->manager->getConnection()->executeQuery(
711
            'SELECT pcs.stream_id as streamId
712
             FROM s_plugin_connect_streams as pcs
713
             WHERE export_status = ?',
714
            [ProductStreamService::STATUS_DELETE]
715
        )->fetchAll();
716
717
        foreach ($streamIds as $stream) {
718
            $streamId = $stream['streamId'];
719
720
            $notDeleted = $this->manager->getConnection()->executeQuery(
721
                'SELECT pss.id
722
                 FROM s_product_streams_selection as pss
723
                 JOIN s_plugin_connect_items as pci
724
                 ON pss.article_id = pci.article_id
725
                 WHERE pss.stream_id = ?
726
                 AND pci.export_status != ?',
727
                [$streamId, null]
728
            )->fetchAll();
729
730
            if (count($notDeleted) === 0) {
731
                $this->manager->getConnection()->executeQuery(
732
                    'UPDATE s_plugin_connect_streams
733
                     SET export_status = ?
734
                     WHERE stream_id = ?',
735
                    [null, $streamId]
736
                );
737
            }
738
        }
739
    }
740
741 View Code Duplication
    private function markStreamsAsSynced()
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...
742
    {
743
        $streamIds = $this->manager->getConnection()->executeQuery(
744
            'SELECT pcs.stream_id as streamId
745
             FROM s_plugin_connect_streams as pcs
746
             WHERE export_status = ?',
747
            [ProductStreamService::STATUS_EXPORT]
748
        )->fetchAll();
749
750
        foreach ($streamIds as $stream) {
751
            $streamId = $stream['streamId'];
752
753
            $notExported = $this->manager->getConnection()->executeQuery(
754
                'SELECT pss.id
755
                 FROM s_product_streams_selection as pss
756
                 JOIN s_plugin_connect_items as pci
757
                 ON pss.article_id = pci.article_id
758
                 WHERE pss.stream_id = ?
759
                 AND pci.export_status != ?',
760
                [$streamId, Attribute::STATUS_SYNCED]
761
            )->fetchAll();
762
763
            if (count($notExported) === 0) {
764
                $this->manager->getConnection()->executeQuery(
765
                    'UPDATE s_plugin_connect_streams
766
                     SET export_status = ?
767
                     WHERE stream_id = ?',
768
                    [ProductStreamService::STATUS_SYNCED, $streamId]
769
                );
770
            }
771
        }
772
    }
773
774
    /**
775
     * @param ConnectAddress $address
776
     */
777
    private function validateBilling(ConnectAddress $address)
778
    {
779
        if (!$address->email) {
780
            throw new \RuntimeException('Billing address should contain email');
781
        }
782
783
        if (!$address->firstName) {
784
            throw new \RuntimeException('Billing address should contain first name');
785
        }
786
787
        if (!$address->surName) {
788
            throw new \RuntimeException('Billing address should contain last name');
789
        }
790
791
        if (!$address->zip) {
792
            throw new \RuntimeException('Billing address should contain zip');
793
        }
794
795
        if (!$address->city) {
796
            throw new \RuntimeException('Billing address should contain city');
797
        }
798
799
        if (!$address->phone) {
800
            throw new \RuntimeException('Billing address should contain phone');
801
        }
802
    }
803
}
804