Completed
Push — master ( a54a4b...bbfdca )
by Adam
15:54
created

ShippingMethodProvider   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 10
dl 0
loc 116
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A getCosts() 0 15 1
B getShippingMethodCosts() 0 17 5
A getCalculator() 0 10 2
B getShippingMethods() 0 15 5
A getCurrentShop() 0 8 2
A isShippingMethodAvailableForClient() 0 11 3
1
<?php
2
/*
3
 * WellCommerce Open-Source E-Commerce Platform
4
 * 
5
 * This file is part of the WellCommerce package.
6
 *
7
 * (c) Adam Piotrowski <[email protected]>
8
 * 
9
 * For the full copyright and license information,
10
 * please view the LICENSE file that was distributed with this source code.
11
 */
12
13
namespace WellCommerce\Bundle\OrderBundle\Provider;
14
15
use Doctrine\Common\Collections\ArrayCollection;
16
use Doctrine\Common\Collections\Collection;
17
use WellCommerce\Bundle\AppBundle\Entity\Client;
18
use WellCommerce\Bundle\AppBundle\Entity\Shop;
19
use WellCommerce\Bundle\AppBundle\Storage\ShopStorageInterface;
20
use WellCommerce\Bundle\CoreBundle\Helper\Security\SecurityHelperInterface;
21
use WellCommerce\Bundle\OrderBundle\Calculator\ShippingCalculatorInterface;
22
use WellCommerce\Bundle\OrderBundle\Calculator\ShippingSubjectInterface;
23
use WellCommerce\Bundle\OrderBundle\Entity\ShippingMethod;
24
use WellCommerce\Bundle\OrderBundle\Entity\ShippingMethodCost;
25
use WellCommerce\Bundle\OrderBundle\Exception\CalculatorNotFoundException;
26
use WellCommerce\Bundle\OrderBundle\Repository\ShippingMethodRepositoryInterface;
27
28
/**
29
 * Class ShippingMethodProvider
30
 *
31
 * @author  Adam Piotrowski <[email protected]>
32
 */
33
final class ShippingMethodProvider implements ShippingMethodProviderInterface
34
{
35
    /**
36
     * @var ShippingMethodRepositoryInterface
37
     */
38
    private $repository;
39
    
40
    /**
41
     * @var Collection
42
     */
43
    private $calculators;
44
    
45
    /**
46
     * @var ShopStorageInterface
47
     */
48
    private $shopStorage;
49
    
50
    /**
51
     * @var SecurityHelperInterface
52
     */
53
    private $securityHelper;
54
    
55
    public function __construct(
56
        ShippingMethodRepositoryInterface $repository,
57
        Collection $calculators,
58
        ShopStorageInterface $shopStorage,
59
        SecurityHelperInterface $securityHelper
60
    ) {
61
        $this->repository     = $repository;
62
        $this->calculators    = $calculators;
63
        $this->shopStorage    = $shopStorage;
64
        $this->securityHelper = $securityHelper;
65
    }
66
    
67
    public function getCosts(ShippingSubjectInterface $subject): Collection
68
    {
69
        $methods    = $this->getShippingMethods($subject);
70
        $collection = new ArrayCollection();
71
        
72
        $methods->map(function (ShippingMethod $shippingMethod) use ($subject, $collection) {
73
            $costs = $this->getShippingMethodCosts($shippingMethod, $subject);
74
            
75
            $costs->map(function (ShippingMethodCost $cost) use ($collection) {
76
                $collection->add($cost);
77
            });
78
        });
79
        
80
        return $collection;
81
    }
82
    
83
    public function getShippingMethodCosts(ShippingMethod $method, ShippingSubjectInterface $subject): Collection
84
    {
85
        $calculator = $this->getCalculator($method);
86
        $country    = $subject->getCountry();
87
        $countries  = $method->getCountries();
88
        $shop       = $this->getCurrentShop($subject);
89
        
90
        if (strlen($country) && count($countries) && !in_array($country, $countries)) {
91
            return new ArrayCollection();
92
        }
93
        
94
        if (false === $method->getShops()->contains($shop)) {
95
            return new ArrayCollection();
96
        }
97
        
98
        return $calculator->calculate($method, $subject);
99
    }
100
    
101
    private function getCalculator(ShippingMethod $shippingMethod): ShippingCalculatorInterface
102
    {
103
        $calculator = $shippingMethod->getCalculator();
104
        
105
        if (false === $this->calculators->containsKey($calculator)) {
106
            throw new CalculatorNotFoundException($calculator);
107
        }
108
        
109
        return $this->calculators->get($calculator);
110
    }
111
    
112
    private function getShippingMethods(ShippingSubjectInterface $subject): Collection
113
    {
114
        $methods = $this->repository->getShippingMethods();
115
        $country = $subject->getCountry();
116
        $shop    = $this->getCurrentShop($subject);
117
        $client  = $this->securityHelper->getCurrentClient();
118
        
119
        return $methods->filter(function (ShippingMethod $method) use ($country, $shop, $client) {
120
            if (strlen($country) && count($method->getCountries()) && !in_array($country, $method->getCountries())) {
121
                return false;
122
            }
123
            
124
            return $method->getShops()->contains($shop) && $this->isShippingMethodAvailableForClient($method, $client);
125
        });
126
    }
127
    
128
    private function getCurrentShop(ShippingSubjectInterface $subject): Shop
129
    {
130
        if (!$subject->getShop() instanceof Shop) {
131
            return $this->shopStorage->getCurrentShop();
132
        }
133
        
134
        return $subject->getShop();
135
    }
136
    
137
    private function isShippingMethodAvailableForClient(ShippingMethod $method, Client $client = null)
138
    {
139
        $clientGroups = $method->getClientGroups();
140
        $clientGroup  = null !== $client ? $client->getClientGroup() : null;
141
        
142
        if ($clientGroups->count()) {
143
            return $clientGroups->contains($clientGroup);
144
        }
145
        
146
        return true;
147
    }
148
}
149