Completed
Push — master ( f1ac10...99c02a )
by Carsten
04:49
created

Basket::remove()   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
2
3
/**
4
 * This file is part of Lenius Basket, a PHP package to handle
5
 * your shopping basket.
6
 *
7
 * Copyright (c) 2017 Lenius.
8
 * https://github.com/lenius/basket
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 *
13
 * @author Carsten Jonstrup<[email protected]>
14
 * @copyright 2017 Lenius.
15
 *
16
 * @version production
17
 *
18
 * @link https://github.com/lenius/basket
19
 */
20
21
namespace Lenius\Basket;
22
23
use InvalidArgumentException;
24
25
class Basket
26
{
27
    protected $id;
28
29
    protected $identifier;
30
    protected $store;
31
32
    protected $currency;
33
34
    protected $requiredParams = [
35
        'id',
36
        'name',
37
        'quantity',
38
        'price',
39
        'weight',
40
    ];
41
42
    /**
43
     * Basket constructor.
44
     *
45
     * @param StorageInterface    $store      The interface for storing the cart data
46
     * @param IdentifierInterface $identifier The interface for storing the identifier
47
     */
48 19
    public function __construct(StorageInterface $store, IdentifierInterface $identifier)
49
    {
50 19
        $this->store = $store;
51 19
        $this->identifier = $identifier;
52
53
        // Generate/retrieve identifier
54 19
        $this->id = $this->identifier->get();
55
56
        // Restore the cart from a saved version
57 19
        if (method_exists($this->store, 'restore')) {
58 19
            $this->store->restore();
59
        }
60
61
        // Let our storage class know which cart we're talking about
62 19
        $this->store->setIdentifier($this->id);
63 19
    }
64
65
    /**
66
     * Retrieve the basket contents.
67
     *
68
     * @param bool $asArray
69
     *
70
     * @return array An array of Item objects
71
     */
72 15
    public function &contents($asArray = false)
73
    {
74 15
        return $this->store->data($asArray);
75
    }
76
77
    /**
78
     * Insert an item into the basket.
79
     *
80
     * @param array $item An array of item data
81
     *
82
     * @return string A unique item identifier
83
     */
84 19
    public function insert(array $item)
85
    {
86 19
        $this->checkArgs($item);
87
88 19
        $itemIdentifier = $this->createItemIdentifier($item);
89
90 19
        if ($this->has($itemIdentifier)) {
91 1
            $item['quantity'] = $this->item($itemIdentifier)->quantity + $item['quantity'];
92 1
            $this->update($itemIdentifier, $item);
93
94 1
            return $itemIdentifier;
95
        }
96
97 19
        $item = new Item($itemIdentifier, $item, $this->store);
98
99 19
        $this->store->insertUpdate($item);
100
101 19
        return $itemIdentifier;
102
    }
103
104
    /**
105
     * Update an item.
106
     *
107
     * @param string           $itemIdentifier The unique item identifier
108
     * @param string|int|array $key            The key to update, or an array of key-value pairs
109
     * @param mixed            $value          The value to set $key to
110
     *
111
     * @return void
112
     */
113 2
    public function update($itemIdentifier, $key, $value = null)
114
    {
115 2
        foreach ($this->contents() as $item) {
116 2
            if ($item->identifier == $itemIdentifier) {
117 2
                $item->update($key, $value);
118 2
                break;
119
            }
120
        }
121 2
    }
122
123
    /**
124
     * Remove an item from the basket.
125
     *
126
     * @param string $identifier Unique item identifier
127
     *
128
     * @return void
129
     */
130 1
    public function remove($identifier)
131
    {
132 1
        $this->store->remove($identifier);
133 1
    }
134
135
    /**
136
     * Destroy/empty the basket.
137
     *
138
     * @return void
139
     */
140 19
    public function destroy()
141
    {
142 19
        $this->store->destroy();
143 19
    }
144
145
    /**
146
     * Check if the basket has a specific item.
147
     *
148
     * @param string $itemIdentifier The unique item identifier
149
     *
150
     * @return bool Yes or no?
151
     */
152 19
    public function has($itemIdentifier)
153
    {
154 19
        return $this->store->has($itemIdentifier);
155
    }
156
157
    /**
158
     * Return a specific item object by identifier.
159
     *
160
     * @param string $itemIdentifier The unique item identifier
161
     *
162
     * @return bool|Item
163
     */
164 5
    public function item($itemIdentifier)
165
    {
166 5
        return $this->store->item($itemIdentifier);
167
    }
168
169
    /**
170
     * Returns the first occurance of an item with a given id.
171
     *
172
     * @param string $id The item id
173
     *
174
     * @return bool|Item
175
     */
176 1
    public function find($id)
177
    {
178 1
        return $this->store->find($id);
179
    }
180
181
    /**
182
     * The total tax value for the basket.
183
     *
184
     * @return float The total tax value
185
     */
186 2
    public function tax()
187
    {
188 2
        $total = 0;
189
190 2
        foreach ($this->contents() as $item) {
191 2
            $total += (float) $item->tax();
192
        }
193
194 2
        return $total;
195
    }
196
197
    /**
198
     * The total weight value for the basket.
199
     *
200
     * @return float The total weight value
201
     */
202 2
    public function weight()
203
    {
204 2
        $weight = 0;
205
206 2
        foreach ($this->contents() as $item) {
207 2
            $weight += (float) $item->weight();
208
        }
209
210 2
        return $weight;
211
    }
212
213
    /**
214
     * The total value of the basket.
215
     *
216
     * @param bool $includeTax Include tax on the total?
217
     *
218
     * @return float The total basket value
219
     */
220 5
    public function total($includeTax = true)
221
    {
222 5
        $total = 0;
223
224 5
        foreach ($this->contents() as $item) {
225 5
            $total += (float) $item->total($includeTax);
226
        }
227
228 5
        return (float) $total;
229
    }
230
231
    /**
232
     * The total number of items in the basket.
233
     *
234
     * @param bool $unique Just return unique items?
235
     *
236
     * @return int Total number of items
237
     */
238 1
    public function totalItems($unique = false)
239
    {
240 1
        $total = 0;
241
242 1
        foreach ($this->contents() as $item) {
243 1
            $total += $unique ? 1 : $item->quantity;
244
        }
245
246 1
        return $total;
247
    }
248
249
    /**
250
     * Set the basket identifier, useful if restoring a saved basket.
251
     *
252
     * @codeCoverageIgnore
253
     * 
254
     * @param string $identifier
255
     *
256
     * @return void
257
     */
258
    public function setIdentifier($identifier)
259
    {
260
        $this->store->setIdentifier($identifier);
261
    }
262
263
    /**
264
     * Create a unique item identifier.
265
     *
266
     * @param array $item An array of item data
267
     *
268
     * @return string An md5 hash of item
269
     */
270 19
    protected function createItemIdentifier(array $item)
271
    {
272 19
        if (!array_key_exists('options', $item)) {
273 14
            $item['options'] = [];
274
        }
275
276 19
        ksort($item['options']);
277
278 19
        return md5($item['id'].serialize($item['options']));
279
    }
280
281
    /**
282
     * Check if a basket item has the required parameters.
283
     *
284
     * @param array $item An array of item data
285
     *
286
     * @return void
287
     */
288 19
    protected function checkArgs(array $item)
289
    {
290 19
        foreach ($this->requiredParams as $param) {
291 19
            if (!array_key_exists($param, $item)) {
292 19
                throw new InvalidArgumentException("The '{$param}' field is required");
293
            }
294
        }
295 19
    }
296
}
297