Completed
Push — 1.0-conflicts ( 05c08f )
by Kamil
54:56
created

OrderFixture::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 30
nc 1
nop 14

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
declare(strict_types=1);
13
14
namespace Sylius\Bundle\CoreBundle\Fixture;
15
16
use Doctrine\Common\Persistence\ObjectManager;
17
use SM\Factory\FactoryInterface as StateMachineFactoryInterface;
18
use Sylius\Bundle\FixturesBundle\Fixture\AbstractFixture;
19
use Sylius\Component\Core\Checker\OrderPaymentMethodSelectionRequirementCheckerInterface;
20
use Sylius\Component\Core\Checker\OrderShippingMethodSelectionRequirementCheckerInterface;
21
use Sylius\Component\Core\Model\AddressInterface;
22
use Sylius\Component\Core\Model\OrderInterface;
23
use Sylius\Component\Core\OrderCheckoutTransitions;
24
use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface;
25
use Sylius\Component\Core\Repository\ShippingMethodRepositoryInterface;
26
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
27
use Sylius\Component\Resource\Factory\FactoryInterface;
28
use Sylius\Component\Resource\Repository\RepositoryInterface;
29
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
30
use Webmozart\Assert\Assert;
31
32
class OrderFixture extends AbstractFixture
33
{
34
    /**
35
     * @var FactoryInterface
36
     */
37
    private $orderFactory;
38
39
    /**
40
     * @var FactoryInterface
41
     */
42
    private $orderItemFactory;
43
44
    /**
45
     * @var OrderItemQuantityModifierInterface
46
     */
47
    private $orderItemQuantityModifier;
48
49
    /**
50
     * @var ObjectManager
51
     */
52
    private $orderManager;
53
54
    /**
55
     * @var RepositoryInterface
56
     */
57
    private $channelRepository;
58
59
    /**
60
     * @var RepositoryInterface
61
     */
62
    private $customerRepository;
63
64
    /**
65
     * @var RepositoryInterface
66
     */
67
    private $productRepository;
68
69
    /**
70
     * @var RepositoryInterface
71
     */
72
    private $countryRepository;
73
74
    /**
75
     * @var PaymentMethodRepositoryInterface
76
     */
77
    private $paymentMethodRepository;
78
79
    /**
80
     * @var ShippingMethodRepositoryInterface
81
     */
82
    private $shippingMethodRepository;
83
84
    /**
85
     * @var FactoryInterface
86
     */
87
    private $addressFactory;
88
89
    /**
90
     * @var StateMachineFactoryInterface
91
     */
92
    private $stateMachineFactory;
93
94
    /**
95
     * @var OrderShippingMethodSelectionRequirementCheckerInterface
96
     */
97
    private $orderShippingMethodSelectionRequirementChecker;
98
99
    /**
100
     * @var OrderPaymentMethodSelectionRequirementCheckerInterface
101
     */
102
    private $orderPaymentMethodSelectionRequirementChecker;
103
104
    /**
105
     * @var \Faker\Generator
106
     */
107
    private $faker;
108
109
    /**
110
     * @param FactoryInterface $orderFactory
111
     * @param FactoryInterface $orderItemFactory
112
     * @param OrderItemQuantityModifierInterface $orderItemQuantityModifier
113
     * @param ObjectManager $orderManager
114
     * @param RepositoryInterface $channelRepository
115
     * @param RepositoryInterface $customerRepository
116
     * @param RepositoryInterface $productRepository
117
     * @param RepositoryInterface $countryRepository
118
     * @param PaymentMethodRepositoryInterface $paymentMethodRepository
119
     * @param ShippingMethodRepositoryInterface $shippingMethodRepository
120
     * @param FactoryInterface $addressFactory
121
     * @param StateMachineFactoryInterface $stateMachineFactory
122
     * @param OrderShippingMethodSelectionRequirementCheckerInterface $orderShippingMethodSelectionRequirementChecker
123
     * @param OrderPaymentMethodSelectionRequirementCheckerInterface $orderPaymentMethodSelectionRequirementChecker
124
     */
125
    public function __construct(
126
        FactoryInterface $orderFactory,
127
        FactoryInterface $orderItemFactory,
128
        OrderItemQuantityModifierInterface $orderItemQuantityModifier,
129
        ObjectManager $orderManager,
130
        RepositoryInterface $channelRepository,
131
        RepositoryInterface $customerRepository,
132
        RepositoryInterface $productRepository,
133
        RepositoryInterface $countryRepository,
134
        PaymentMethodRepositoryInterface $paymentMethodRepository,
135
        ShippingMethodRepositoryInterface $shippingMethodRepository,
136
        FactoryInterface $addressFactory,
137
        StateMachineFactoryInterface $stateMachineFactory,
138
        OrderShippingMethodSelectionRequirementCheckerInterface $orderShippingMethodSelectionRequirementChecker,
139
        OrderPaymentMethodSelectionRequirementCheckerInterface $orderPaymentMethodSelectionRequirementChecker
140
    ) {
141
        $this->orderFactory = $orderFactory;
142
        $this->orderItemFactory = $orderItemFactory;
143
        $this->orderItemQuantityModifier = $orderItemQuantityModifier;
144
        $this->orderManager = $orderManager;
145
        $this->channelRepository = $channelRepository;
146
        $this->customerRepository = $customerRepository;
147
        $this->productRepository = $productRepository;
148
        $this->countryRepository = $countryRepository;
149
        $this->paymentMethodRepository = $paymentMethodRepository;
150
        $this->shippingMethodRepository = $shippingMethodRepository;
151
        $this->addressFactory = $addressFactory;
152
        $this->stateMachineFactory = $stateMachineFactory;
153
        $this->orderShippingMethodSelectionRequirementChecker = $orderShippingMethodSelectionRequirementChecker;
154
        $this->orderPaymentMethodSelectionRequirementChecker = $orderPaymentMethodSelectionRequirementChecker;
155
156
        $this->faker = \Faker\Factory::create();
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162
    public function load(array $options): void
163
    {
164
        $channels = $this->channelRepository->findAll();
165
        $customers = $this->customerRepository->findAll();
166
        $countries = $this->countryRepository->findAll();
167
168
        for ($i = 0; $i < $options['amount']; ++$i) {
169
            $channel = $this->faker->randomElement($channels);
170
            $customer = $this->faker->randomElement($customers);
171
            $countryCode = $this->faker->randomElement($countries)->getCode();
172
173
            $currencyCode = $channel->getBaseCurrency()->getCode();
174
            $localeCode = $this->faker->randomElement($channel->getLocales()->toArray())->getCode();
175
176
            $order = $this->orderFactory->createNew();
177
            $order->setChannel($channel);
178
            $order->setCustomer($customer);
179
            $order->setCurrencyCode($currencyCode);
180
            $order->setLocaleCode($localeCode);
181
182
            $this->generateItems($order);
183
184
            $this->address($order, $countryCode);
185
            $this->selectShipping($order);
186
            $this->selectPayment($order);
187
            $this->completeCheckout($order);
188
189
            $this->orderManager->persist($order);
190
191
            if (0 === ($i % 50)) {
192
                $this->orderManager->flush();
193
            }
194
        }
195
196
        $this->orderManager->flush();
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202
    public function getName(): string
203
    {
204
        return 'order';
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void
211
    {
212
        $optionsNode
0 ignored issues
show
Unused Code introduced by
The call to the method Symfony\Component\Config...erNodeDefinition::end() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
213
            ->children()
214
                ->integerNode('amount')->isRequired()->min(0)->end()
215
        ;
216
    }
217
218
    /**
219
     * @param OrderInterface $order
220
     */
221
    private function generateItems(OrderInterface $order): void
222
    {
223
        $numberOfItems = random_int(1, 5);
224
        $products = $this->productRepository->findAll();
225
226
        for ($i = 0; $i < $numberOfItems; ++$i) {
227
            $item = $this->orderItemFactory->createNew();
228
229
            $product = $this->faker->randomElement($products);
230
            $variant = $this->faker->randomElement($product->getVariants()->toArray());
231
232
            $item->setVariant($variant);
233
            $this->orderItemQuantityModifier->modify($item, random_int(1, 5));
234
235
            $order->addItem($item);
236
        }
237
    }
238
239
    /**
240
     * @param OrderInterface $order
241
     * @param string $countryCode
242
     */
243
    private function address(OrderInterface $order, string $countryCode): void
244
    {
245
        /** @var AddressInterface $address */
246
        $address = $this->addressFactory->createNew();
247
        $address->setFirstName($this->faker->firstName);
248
        $address->setLastName($this->faker->lastName);
249
        $address->setStreet($this->faker->streetName);
250
        $address->setCountryCode($countryCode);
251
        $address->setCity($this->faker->city);
252
        $address->setPostcode($this->faker->postcode);
253
254
        $order->setShippingAddress($address);
255
        $order->setBillingAddress(clone $address);
256
257
        $this->applyCheckoutStateTransition($order, OrderCheckoutTransitions::TRANSITION_ADDRESS);
258
    }
259
260
    /**
261
     * @param OrderInterface $order
262
     */
263
    private function selectShipping(OrderInterface $order): void
264
    {
265
        $shippingMethod = $this
266
            ->faker
267
            ->randomElement($this->shippingMethodRepository->findEnabledForChannel($order->getChannel()))
0 ignored issues
show
Documentation introduced by
$order->getChannel() is of type object<Sylius\Component\...\ChannelInterface>|null, but the function expects a object<Sylius\Component\...Model\ChannelInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
268
        ;
269
        Assert::notNull($shippingMethod, 'Shipping method should not be null.');
270
271
        foreach ($order->getShipments() as $shipment) {
272
            $shipment->setMethod($shippingMethod);
273
        }
274
275
        if ($this->orderShippingMethodSelectionRequirementChecker->isShippingMethodSelectionRequired($order)) {
276
            $this->applyCheckoutStateTransition($order, OrderCheckoutTransitions::TRANSITION_SELECT_SHIPPING);
277
        }
278
    }
279
280
    /**
281
     * @param OrderInterface $order
282
     */
283
    private function selectPayment(OrderInterface $order): void
284
    {
285
        $paymentMethod = $this
286
            ->faker
287
            ->randomElement($this->paymentMethodRepository->findEnabledForChannel($order->getChannel()))
0 ignored issues
show
Documentation introduced by
$order->getChannel() is of type object<Sylius\Component\...\ChannelInterface>|null, but the function expects a object<Sylius\Component\...Model\ChannelInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
288
        ;
289
        Assert::notNull($paymentMethod, 'Payment method should not be null.');
290
291
        foreach ($order->getPayments() as $payment) {
292
            $payment->setMethod($paymentMethod);
293
        }
294
295
        if ($this->orderPaymentMethodSelectionRequirementChecker->isPaymentMethodSelectionRequired($order)) {
296
            $this->applyCheckoutStateTransition($order, OrderCheckoutTransitions::TRANSITION_SELECT_PAYMENT);
297
        }
298
    }
299
300
    /**
301
     * @param OrderInterface $order
302
     */
303
    private function completeCheckout(OrderInterface $order): void
304
    {
305
        if ($this->faker->boolean(25)) {
306
            $order->setNotes($this->faker->sentence);
307
        }
308
309
        $this->applyCheckoutStateTransition($order, OrderCheckoutTransitions::TRANSITION_COMPLETE);
310
    }
311
312
    /**
313
     * @param OrderInterface $order
314
     * @param string $transition
315
     */
316
    private function applyCheckoutStateTransition(OrderInterface $order, string $transition): void
317
    {
318
        $this->stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->apply($transition);
319
    }
320
}
321