Passed
Push — master ( 33b9bf...a11b84 )
by Dariusz
03:33 queued 10s
created

Cart::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of the Plane\Shop package.
5
 *
6
 * (c) Dariusz Korsak <[email protected]>
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 Plane\Shop;
13
14
use Money\Money;
15
use Money\Currency;
16
use OutOfBoundsException;
17
use Plane\Shop\PaymentInterface;
18
use Plane\Shop\CartItemInterface;
19
use Plane\Shop\ShippingInterface;
20
use Plane\Shop\CartItemCollection;
21
use Plane\Shop\CartDiscountInterface;
22
23
final class Cart implements CartInterface
24
{
25
    private $items = [];
26
27
    private $currency;
28
    
29
    private $shipping;
30
    
31
    private $payment;
32
    
33
    private $discounts = [];
34
    
35 36
    public function __construct(string $currency)
36
    {
37 36
        $this->currency = $currency;
38 36
    }
39
40 6
    public function getCurrency(): string
41
    {
42 6
        return $this->currency;
43
    }
44
45 35
    public function setShipping(ShippingInterface $shipping): void
46
    {
47 35
        $this->shipping = $shipping;
48 35
    }
49
    
50 3
    public function getShipping(): ?ShippingInterface
51
    {
52 3
        return $this->shipping;
53
    }
54
    
55 35
    public function setPayment(PaymentInterface $payment): void
56
    {
57 35
        $this->payment = $payment;
58 35
    }
59
    
60 3
    public function getPayment(): ?PaymentInterface
61
    {
62 3
        return $this->payment;
63
    }
64
    
65 3
    public function addDiscount(CartDiscountInterface $discount): void
66
    {
67 3
        $this->discounts[] = $discount;
68 3
    }
69
70 2
    public function getDiscounts(): array
71
    {
72 2
        return $this->discounts;
73
    }
74
    
75 1
    public function fill(CartItemCollection $collection): void
76
    {
77
        array_map(function ($item) {
78 1
            $this->addItem($item);
79 1
        }, $collection->getItems());
80 1
    }
81
82 35
    public function add(CartItemInterface $item): void
83
    {
84
        // if product already in the cart, increase quantity
85 35
        if ($this->has($item->getId())) {
86 1
            $this->get($item->getId())->increaseQuantity($item->getQuantity());
87 1
            return;
88
        }
89
        
90 35
        $this->addItem($item);
91 35
    }
92
    
93 4
    public function remove(string $itemId): void
94
    {
95 4
        if (!$this->has($itemId)) {
96 2
            throw new OutOfBoundsException('Item ' . $itemId . ' not found');
97
        }
98
        
99 2
        unset($this->items[$itemId]);
100 2
    }
101
102 2
    public function clear(): void
103
    {
104 2
        $this->items = [];
105 2
    }
106
      
107 2
    public function update(CartItemInterface $item): void
108
    {
109 2
        $this->addItem($item);
110 2
    }
111
    
112 35
    public function has(string $itemId): bool
113
    {
114 35
        return array_key_exists($itemId, $this->items);
115
    }
116
117 5
    public function get(string $itemId): CartItemInterface
118
    {
119 5
        if (!$this->has($itemId)) {
120 2
            throw new OutOfBoundsException('Item ' . $itemId . ' not found');
121
        }
122
        
123 3
        return $this->items[$itemId];
124
    }
125
    
126 8
    public function items(): array
127
    {
128 8
        return $this->items;
129
    }
130
    
131 4
    public function itemsQuantity(): int
132
    {
133 4
        return (int) array_sum(
134
            array_map(function (CartItemInterface $item) {
135 4
                return $item->getQuantity();
136 4
            }, $this->items)
137
        );
138
    }
139
140 2
    public function weight(): string
141
    {
142 2
        return (string) array_sum(
143
            array_map(function (CartItemInterface $item) {
144 2
                return $item->getWeightTotal();
145 2
            }, $this->items)
146
        );
147
    }
148
149 3
    public function totalNet(): Money
150
    {
151
        $total = array_map(function (CartItemInterface $item) {
152 3
            return $item->getPriceTotal($this->currency);
153 3
        }, $this->items);
154
        
155 3
        return $this->sumPrices($total);
156
    }
157
158 7
    public function totalGross(): Money
159
    {
160
        $total = array_map(function (CartItemInterface $item) {
161 6
            return $item->getPriceTotalWithTax($this->currency);
162 7
        }, $this->items);
163
        
164 7
        return $this->sumPrices($total);
165
    }
166
    
167 3
    public function tax(): Money
168
    {
169
        $total = array_map(function (CartItemInterface $item) {
170 3
            return $item->getTaxTotal($this->currency);
171 3
        }, $this->items);
172
173 3
        return $this->sumPrices($total);
174
    }
175
    
176 6
    public function totalAfterDiscounts(): Money
177
    {
178 6
        return !empty($this->discounts)
179 2
            ? end($this->discounts)->getPriceAfterDiscount()
180 6
            : $this->totalGross();
181
    }
182
183 5
    public function shippingCost(): Money
184
    {
185 5
        if (!$this->shipping instanceof ShippingInterface) {
186 1
            return new Money(0, new Currency($this->currency));
187
        }
188
        
189 4
        return $this->shipping->getCost($this->currency);
190
    }
191
    
192 4
    public function paymentFee(): Money
193
    {
194 4
        if (!$this->payment instanceof PaymentInterface) {
195 1
            return new Money(0, new Currency($this->currency));
196
        }
197
198 3
        return $this->payment->getFee($this->totalAfterDiscounts()->add($this->shippingCost()), $this->currency);
199
    }
200
    
201 35
    private function addItem(CartItemInterface $item)
202
    {
203 35
        $this->items[$item->getId()] = $item;
204 35
    }
205
206 9
    private function sumPrices(array $prices): Money
207
    {
208 9
        $money = new Money(0, new Currency($this->currency));
209
210 9
        return call_user_func_array([$money, 'add'], $prices);
211
    }
212
}
213