Completed
Push — master ( d54afb...01173a )
by Kamil
26:45
created

OrderContext::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 25
rs 8.8571
cc 1
eloc 23
nc 1
nop 11

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Behat\Context\Setup;
13
14
use Behat\Behat\Context\Context;
15
use Doctrine\Common\Persistence\ObjectManager;
16
use Sylius\Component\Core\Model\ChannelInterface;
17
use Sylius\Component\Core\Model\CouponInterface;
18
use Sylius\Component\Core\OrderProcessing\OrderRecalculatorInterface;
19
use Sylius\Component\Currency\Model\CurrencyInterface;
20
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
21
use Sylius\Component\Core\Model\AddressInterface;
22
use Sylius\Component\Core\Model\OrderInterface;
23
use Sylius\Component\Core\Model\OrderItemInterface;
24
use Sylius\Component\Core\Model\ProductInterface;
25
use Sylius\Component\Core\Model\ProductVariantInterface;
26
use Sylius\Component\Core\Model\ShippingMethodInterface;
27
use Sylius\Component\Core\OrderProcessing\OrderShipmentProcessorInterface;
28
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
29
use Sylius\Component\Core\Test\Services\SharedStorageInterface;
30
use Sylius\Component\Payment\Factory\PaymentFactoryInterface;
31
use Sylius\Component\Payment\Model\PaymentInterface;
32
use Sylius\Component\Payment\Model\PaymentMethodInterface;
33
use Sylius\Component\Resource\Factory\FactoryInterface;
34
use Sylius\Component\Resource\Repository\RepositoryInterface;
35
use Sylius\Component\User\Model\CustomerInterface;
36
use Sylius\Component\User\Model\UserInterface;
37
38
/**
39
 * @author Łukasz Chruściel <[email protected]>
40
 */
41
final class OrderContext implements Context
42
{
43
    /**
44
     * @var SharedStorageInterface
45
     */
46
    private $sharedStorage;
47
48
    /**
49
     * @var OrderRepositoryInterface
50
     */
51
    private $orderRepository;
52
53
    /**
54
     * @var FactoryInterface
55
     */
56
    private $orderFactory;
57
58
    /**
59
     * @var OrderShipmentProcessorInterface
60
     */
61
    private $orderShipmentFactory;
62
63
    /**
64
     * @var PaymentFactoryInterface
65
     */
66
    private $paymentFactory;
67
68
    /**
69
     * @var FactoryInterface
70
     */
71
    private $orderItemFactory;
72
73
    /**
74
     * @var OrderItemQuantityModifierInterface
75
     */
76
    private $itemQuantityModifier;
77
78
    /**
79
     * @var FactoryInterface
80
     */
81
    private $customerFactory;
82
83
    /**
84
     * @var RepositoryInterface
85
     */
86
    private $customerRepository;
87
88
    /**
89
     * @var OrderRecalculatorInterface
90
     */
91
    private $orderRecalculator;
92
93
    /**
94
     * @var ObjectManager
95
     */
96
    private $objectManager;
97
98
    /**
99
     * @param SharedStorageInterface $sharedStorage
100
     * @param OrderRepositoryInterface $orderRepository
101
     * @param FactoryInterface $orderFactory
102
     * @param OrderShipmentProcessorInterface $orderShipmentFactory
103
     * @param PaymentFactoryInterface $paymentFactory
104
     * @param FactoryInterface $orderItemFactory
105
     * @param OrderItemQuantityModifierInterface $itemQuantityModifier
106
     * @param FactoryInterface $customerFactory
107
     * @param RepositoryInterface $customerRepository
108
     * @param OrderRecalculatorInterface $orderRecalculator
109
     * @param ObjectManager $objectManager
110
     */
111
    public function __construct(
112
        SharedStorageInterface $sharedStorage,
113
        OrderRepositoryInterface $orderRepository,
114
        FactoryInterface $orderFactory,
115
        OrderShipmentProcessorInterface $orderShipmentFactory,
116
        PaymentFactoryInterface $paymentFactory,
117
        FactoryInterface $orderItemFactory,
118
        OrderItemQuantityModifierInterface $itemQuantityModifier,
119
        FactoryInterface $customerFactory,
120
        RepositoryInterface $customerRepository,
121
        OrderRecalculatorInterface $orderRecalculator,
122
        ObjectManager $objectManager
123
    ) {
124
        $this->sharedStorage = $sharedStorage;
125
        $this->orderRepository = $orderRepository;
126
        $this->orderFactory = $orderFactory;
127
        $this->orderShipmentFactory = $orderShipmentFactory;
128
        $this->paymentFactory = $paymentFactory;
129
        $this->orderItemFactory = $orderItemFactory;
130
        $this->itemQuantityModifier = $itemQuantityModifier;
131
        $this->customerFactory = $customerFactory;
132
        $this->customerRepository = $customerRepository;
133
        $this->orderRecalculator = $orderRecalculator;
134
        $this->objectManager = $objectManager;
135
    }
136
137
    /**
138
     * @Given there is a customer :customer that placed an order :orderNumber
139
     */
140
    public function thereIsCustomerThatPlacedOrder(CustomerInterface $customer, $orderNumber)
141
    {
142
        $order = $this->createOrder($customer, $orderNumber);
143
144
        $this->sharedStorage->set('order', $order);
145
146
        $this->orderRepository->add($order);
147
    }
148
149
    /**
150
     * @Given /^the customer ("[^"]+" addressed it to "[^"]+", "[^"]+" "[^"]+" in the "[^"]+")$/
151
     */
152
    public function theCustomerAddressedItTo(AddressInterface $address)
153
    {
154
        /** @var OrderInterface $order */
155
        $order = $this->sharedStorage->get('order');
156
        $order->setShippingAddress($address);
157
158
        $this->objectManager->flush();
159
    }
160
161
    /**
162
     * @Given /^for the billing address (of "[^"]+" in the "[^"]+", "[^"]+" "[^"]+", "[^"]+")$/
163
     */
164
    public function forTheBillingAddressOf(AddressInterface $address)
165
    {
166
        /** @var OrderInterface $order */
167
        $order = $this->sharedStorage->get('order');
168
169
        $order->setBillingAddress($address);
170
171
        $this->objectManager->flush();
172
    }
173
174
    /**
175
     * @Given /^the customer chose ("[^"]+" shipping method) (to "[^"]+") with ("[^"]+" payment)$/
176
     */
177
    public function theCustomerChoseShippingToWithPayment(
178
        ShippingMethodInterface $shippingMethod,
179
        AddressInterface $address,
180
        PaymentMethodInterface $paymentMethod
181
    ) {
182
        /** @var OrderInterface $order */
183
        $order = $this->sharedStorage->get('order');
184
185
        $this->orderShipmentFactory->processOrderShipment($order);
186
        $order->getShipments()->first()->setMethod($shippingMethod);
187
188
        $payment = $this->paymentFactory->createWithAmountAndCurrency($order->getTotal(), $order->getCurrency());
189
        $payment->setMethod($paymentMethod);
190
191
        $order->addPayment($payment);
192
193
        $order->setShippingAddress($address);
194
        $order->setBillingAddress($address);
195
196
        $this->orderRecalculator->recalculate($order);
197
198
        $this->objectManager->flush();
199
    }
200
201
    /**
202
     * @Given /^the customer chose ("[^"]+" shipping method) with ("[^"]+" payment)$/
203
     */
204
    public function theCustomerChoseShippingWithPayment(
205
        ShippingMethodInterface $shippingMethod,
206
        PaymentMethodInterface $paymentMethod
207
    ) {
208
        /** @var OrderInterface $order */
209
        $order = $this->sharedStorage->get('order');
210
211
        $this->orderShipmentFactory->processOrderShipment($order);
212
        $order->getShipments()->first()->setMethod($shippingMethod);
213
214
        $this->orderRecalculator->recalculate($order);
215
216
        $payment = $this->paymentFactory->createWithAmountAndCurrency($order->getTotal(), $order->getCurrency());
217
        $payment->setMethod($paymentMethod);
218
219
        $order->addPayment($payment);
220
221
        $this->objectManager->flush();
222
    }
223
224
    /**
225
     * @Given the customer bought a single :product
226
     */
227
    public function theCustomerBoughtSingleProduct(ProductInterface $product)
228
    {
229
        $this->addProductVariantToOrder($product->getMasterVariant(), $product->getPrice(), 1);
230
231
        $this->objectManager->flush();
232
    }
233
234
    /**
235
     * @Given /^the customer bought ((?:a|an) "[^"]+") and ((?:a|an) "[^"]+")$/
236
     */
237
    public function theCustomerBoughtProductAndProduct(ProductInterface $product, ProductInterface $secondProduct)
238
    {
239
        $this->theCustomerBoughtSingleProduct($product);
240
        $this->theCustomerBoughtSingleProduct($secondProduct);
241
    }
242
243
244
    /**
245
     * @Given /^the customer bought (\d+) ("[^"]+" products)/
246
     */
247
    public function theCustomerBoughtSeveralProducts($quantity, ProductInterface $product)
248
    {
249
        $this->addProductVariantToOrder($product->getMasterVariant(), $product->getPrice(), $quantity);
250
251
        $this->objectManager->flush();
252
    }
253
254
    /**
255
     * @Given /^the customer bought a single ("[^"]+" variant of product "[^"]+")$/
256
     */
257
    public function theCustomerBoughtSingleProductVariant(ProductVariantInterface $productVariant)
258
    {
259
        $this->addProductVariantToOrder($productVariant, $productVariant->getPrice());
260
261
        $this->objectManager->flush();
262
    }
263
264
    /**
265
     * @Given the customer bought a single :product using :coupon coupon
266
     */
267
    public function theCustomerBoughtSingleUsing(ProductInterface $product, CouponInterface $coupon)
268
    {
269
        $order = $this->addProductVariantToOrder($product->getMasterVariant(), $product->getPrice());
270
        $order->setPromotionCoupon($coupon);
271
272
        $this->orderRecalculator->recalculate($order);
273
274
        $this->objectManager->flush();
275
    }
276
277
    /**
278
     * @Given /^(I) have already placed an order (\d+) times$/
279
     */
280
    public function iHaveAlreadyPlacedOrderNthTimes(UserInterface $user, $numberOfOrders)
281
    {
282
        $customer = $user->getCustomer();
283
        for ($i = 0; $i < $numberOfOrders; $i++) {
284
            $order = $this->createOrder($customer, '#00000'.$i);
285
            $order->setPaymentState(PaymentInterface::STATE_COMPLETED);
286
            $order->setCompletedAt(new \DateTime());
287
288
            $this->orderRepository->add($order);
289
        }
290
    }
291
292
    /**
293
     * @Given :numberOfCustomers customers have added products to the cart for total of :total
294
     */
295
    public function customersHaveAddedProductsToTheCartForTotalOf($numberOfCustomers, $total)
296
    {
297
        $customers = $this->generateCustomers($numberOfCustomers);
298
299
        $sampleProductVariant = $this->sharedStorage->get('variant');
300
        $total = $this->getPriceFromString($total);
301
302
        for ($i = 0; $i < $numberOfCustomers; $i++) {
303
            $order = $this->createOrder($customers[rand(0, $numberOfCustomers - 1)]);
304
            $order->setCompletedAt(null);
305
306
            $price = $i === ($numberOfCustomers - 1) ? $total : rand(1, $total);
307
            $total -= $price;
308
309
            $item = $this->orderItemFactory->createNew();
310
            $item->setVariant($sampleProductVariant);
311
            $item->setUnitPrice($price);
312
313
            $this->itemQuantityModifier->modify($item, 1);
314
315
            $order->addItem($item);
316
317
            $this->orderRepository->add($order);
318
        }
319
    }
320
321
    /**
322
     * @Given :numberOfCustomers customers have placed :numberOfOrders orders for total of :total
323
     * @Given then :numberOfCustomers more customers have placed :numberOfOrders orders for total of :total
324
     */
325
    public function customersHavePlacedOrdersForTotalOf($numberOfCustomers, $numberOfOrders, $total)
326
    {
327
        $customers = $this->generateCustomers($numberOfCustomers);
328
        $sampleProductVariant = $this->sharedStorage->get('variant');
329
        $total = $this->getPriceFromString($total);
330
331
        for ($i = 0; $i < $numberOfOrders; $i++) {
332
            $order = $this->createOrder($customers[rand(0, $numberOfCustomers - 1)], '#'.uniqid());
333
            $order->setPaymentState(PaymentInterface::STATE_COMPLETED);
334
            $order->setCompletedAt(new \DateTime());
335
336
            $price = $i === ($numberOfOrders - 1) ? $total : rand(1, $total);
337
            $total -= $price;
338
339
            $item = $this->orderItemFactory->createNew();
340
            $item->setVariant($sampleProductVariant);
341
            $item->setUnitPrice($price);
342
343
            $this->itemQuantityModifier->modify($item, 1);
344
345
            $order->addItem($item);
346
347
            $this->orderRepository->add($order);
348
        }
349
    }
350
351
    /**
352
     * @param ProductVariantInterface $productVariant
353
     * @param int $price
354
     * @param int $quantity
355
     *
356
     * @return OrderInterface
357
     */
358
    private function addProductVariantToOrder(ProductVariantInterface $productVariant, $price, $quantity = 1)
359
    {
360
        $order = $this->sharedStorage->get('order');
361
362
        /** @var OrderItemInterface $item */
363
        $item = $this->orderItemFactory->createNew();
364
        $item->setVariant($productVariant);
365
        $item->setUnitPrice($price);
366
367
        $this->itemQuantityModifier->modify($item, $quantity);
368
369
        $order->addItem($item);
370
371
        $this->orderRecalculator->recalculate($order);
372
373
        return $order;
374
    }
375
376
    /**
377
     * @param CustomerInterface $customer
378
     * @param string $number
379
     * @param ChannelInterface|null $channel
380
     * @param CurrencyInterface|null $currency
381
     *
382
     * @return OrderInterface
383
     */
384
    private function createOrder(
385
        CustomerInterface $customer,
386
        $number = null,
387
        ChannelInterface $channel = null,
388
        CurrencyInterface $currency = null
389
    ) {
390
        $order = $this->orderFactory->createNew();
391
392
        $order->setCustomer($customer);
393
        $order->setNumber($number);
394
        $order->setChannel((null !== $channel) ? $channel : $this->sharedStorage->get('channel'));
395
        $order->setCurrency((null !== $currency) ? $currency : $this->sharedStorage->get('currency'));
396
        $order->complete();
397
398
        return $order;
399
    }
400
401
    /**
402
     * @param $count
403
     *
404
     * @return CustomerInterface[]
405
     */
406
    private function generateCustomers($count)
407
    {
408
        $customers = [];
409
410
        for ($i = 0; $i < $count; $i++) {
411
            $customer = $this->customerFactory->createNew();
412
            $customer->setEmail(sprintf('john%[email protected]', uniqid()));
413
            $customer->setFirstname('John');
414
            $customer->setLastname('Doe'.$i);
415
416
            $customers[] = $customer;
417
418
            $this->customerRepository->add($customer);
419
        }
420
421
        return $customers;
422
    }
423
424
    /**
425
     * @param string $price
426
     *
427
     * @return int
428
     */
429
    private function getPriceFromString($price)
430
    {
431
        return (int) round((str_replace(['€', '£', '$'], '', $price) * 100), 2);
432
    }
433
}
434