Completed
Pull Request — master (#272)
by Felipe
38:19
created

ChooseShippingMethodHandler   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 5
lcom 1
cbo 10
dl 0
loc 97
rs 10
c 1
b 1
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 1
B handle() 0 27 1
A getShipmentsAvailable() 0 12 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Sylius\ShopApiPlugin\Handler;
6
7
use Doctrine\Common\Collections\Collection;
8
use SM\Factory\FactoryInterface;
9
use Sylius\Component\Core\Model\OrderInterface;
10
use Sylius\Component\Core\Model\ShippingMethodInterface;
11
use Sylius\Component\Core\OrderCheckoutTransitions;
12
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
13
use Sylius\Component\Core\Repository\ShippingMethodRepositoryInterface;
14
use Sylius\Component\Shipping\Checker\ShippingMethodEligibilityCheckerInterface;
15
use Sylius\Component\Shipping\Resolver\ShippingMethodsResolverInterface;
16
use Sylius\ShopApiPlugin\Command\ChooseShippingMethod;
17
use Webmozart\Assert\Assert;
18
19
final class ChooseShippingMethodHandler
20
{
21
    /**
22
     * @var OrderRepositoryInterface
23
     */
24
    private $orderRepository;
25
26
    /**
27
     * @var ShippingMethodRepositoryInterface
28
     */
29
    private $shippingMethodRepository;
30
31
    /**
32
     * @var ShippingMethodEligibilityCheckerInterface
33
     */
34
    private $eligibilityChecker;
35
36
    /**
37
     * @var FactoryInterface
38
     */
39
    private $stateMachineFactory;
40
41
    /**
42
     * @var ShippingMethodsResolverInterface
43
     */
44
    private $shippingMethodsResolver;
45
46
    /**
47
     * @param OrderRepositoryInterface $orderRepository
48
     * @param ShippingMethodRepositoryInterface $shippingMethodRepository
49
     * @param ShippingMethodEligibilityCheckerInterface $eligibilityChecker
50
     * @param ShippingMethodsResolverInterface $shippingMethodsResolver
51
     * @param FactoryInterface $stateMachineFactory
52
     */
53
    public function __construct(
54
        OrderRepositoryInterface $orderRepository,
55
        ShippingMethodRepositoryInterface $shippingMethodRepository,
56
        ShippingMethodEligibilityCheckerInterface $eligibilityChecker,
57
        ShippingMethodsResolverInterface $shippingMethodsResolver,
58
        FactoryInterface $stateMachineFactory
59
    ) {
60
        $this->orderRepository = $orderRepository;
61
        $this->shippingMethodRepository = $shippingMethodRepository;
62
        $this->eligibilityChecker = $eligibilityChecker;
63
        $this->stateMachineFactory = $stateMachineFactory;
64
        $this->shippingMethodsResolver = $shippingMethodsResolver;
65
    }
66
67
    /**
68
     * @param ChooseShippingMethod $chooseShippingMethod
69
     */
70
    public function handle(ChooseShippingMethod $chooseShippingMethod)
71
    {
72
        /** @var OrderInterface $cart */
73
        $cart = $this->orderRepository->findOneBy(['tokenValue' => $chooseShippingMethod->orderToken()]);
74
75
        Assert::notNull($cart, 'Cart has not been found.');
76
77
        $stateMachine = $this->stateMachineFactory->get($cart, OrderCheckoutTransitions::GRAPH);
78
79
        Assert::true($stateMachine->can(OrderCheckoutTransitions::TRANSITION_SELECT_SHIPPING), 'Order cannot have shipment method assigned.');
80
81
        /** @var ShippingMethodInterface $shippingMethod */
82
        $shippingMethod = $this->shippingMethodRepository->findOneBy(['code' => $chooseShippingMethod->shippingMethod()]);
83
84
        Assert::notNull($shippingMethod, 'Shipping method has not been found');
85
86
        $shipmentsAvailable = $this->getShipmentsAvailable($cart->getShipments());
0 ignored issues
show
Bug introduced by
It seems like $cart->getShipments() targeting Sylius\Component\Core\Mo...terface::getShipments() can also be of type array<integer,object<Syl...del\ShipmentInterface>>; however, Sylius\ShopApiPlugin\Han...getShipmentsAvailable() does only seem to accept object<Doctrine\Common\Collections\Collection>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
87
88
        Assert::true(isset($shipmentsAvailable[$chooseShippingMethod->shipmentIdentifier()]), 'Can not find shipment with given identifier.');
89
90
        $shipment = $shipmentsAvailable[$chooseShippingMethod->shipmentIdentifier()];
91
92
        Assert::true($this->eligibilityChecker->isEligible($shipment, $shippingMethod), 'Given shipment is not eligible for provided shipping method.');
93
94
        $shipment->setMethod($shippingMethod);
95
        $stateMachine->apply(OrderCheckoutTransitions::TRANSITION_SELECT_SHIPPING);
96
    }
97
98
    /**
99
     * @param Collection $shipments
100
     *
101
     * @return array
102
     */
103
    private function getShipmentsAvailable(Collection $shipments): array
104
    {
105
        $shipmentsAvailable = [];
106
        foreach ($shipments as $shipment) {
107
            /** @var ShippingMethodInterface $shippingMethod */
108
            foreach ($this->shippingMethodsResolver->getSupportedMethods($shipment) as $shippingMethod) {
109
                $shipmentsAvailable[$shippingMethod->getCode()] = $shipment;
110
            }
111
        }
112
113
        return $shipmentsAvailable;
114
    }
115
}
116