Completed
Push — master ( d998d0...abb41b )
by Kamil
38:34
created

OrderItem::hasAdjustment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
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
namespace Sylius\Component\Order\Model;
13
14
use Doctrine\Common\Collections\ArrayCollection;
15
use Doctrine\Common\Collections\Collection;
16
17
/**
18
 * @author Paweł Jędrzejewski <[email protected]>
19
 * @author Michał Marcinkowski <[email protected]>
20
 */
21
class OrderItem implements OrderItemInterface
22
{
23
    /**
24
     * @var mixed
25
     */
26
    protected $id;
27
28
    /**
29
     * @var OrderInterface
30
     */
31
    protected $order;
32
33
    /**
34
     * @var int
35
     */
36
    protected $quantity = 0;
37
38
    /**
39
     * @var int
40
     */
41
    protected $unitPrice = 0;
42
43
    /**
44
     * @var int
45
     */
46
    protected $total = 0;
47
48
    /**
49
     * @var bool
50
     */
51
    protected $immutable = false;
52
53
    /**
54
     * @var Collection|OrderItemUnitInterface[]
55
     */
56
    protected $units;
57
58
    /**
59
     * @var int
60
     */
61
    protected $unitsTotal = 0;
62
63
    /**
64
     * @var Collection|AdjustmentInterface[]
65
     */
66
    protected $adjustments;
67
68
    /**
69
     * @var int
70
     */
71
    protected $adjustmentsTotal = 0;
72
73
    public function __construct()
74
    {
75
        $this->adjustments = new ArrayCollection();
76
        $this->units = new ArrayCollection();
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82
    public function getId()
83
    {
84
        return $this->id;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function getQuantity()
91
    {
92
        return $this->quantity;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function getOrder()
99
    {
100
        return $this->order;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function setOrder(OrderInterface $order = null)
107
    {
108
        $currentOrder = $this->getOrder();
109
        if ($currentOrder === $order) {
110
            return;
111
        }
112
113
        $this->order = null;
114
115
        if (null !== $currentOrder) {
116
            $currentOrder->removeItem($this);
117
        }
118
119
        if (null === $order) {
120
            return;
121
        }
122
123
        $this->order = $order;
124
125
        if (!$order->hasItem($this)) {
126
            $order->addItem($this);
127
        }
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function getUnitPrice()
134
    {
135
        return $this->unitPrice;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public function setUnitPrice($unitPrice)
142
    {
143
        if (!is_int($unitPrice)) {
144
            throw new \InvalidArgumentException('Unit price must be an integer.');
145
        }
146
147
        $this->unitPrice = $unitPrice;
148
        $this->recalculateUnitsTotal();
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public function getTotal()
155
    {
156
        return $this->total;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162
    public function recalculateAdjustmentsTotal()
163
    {
164
        $this->adjustmentsTotal = 0;
165
166
        foreach ($this->adjustments as $adjustment) {
167
            if (!$adjustment->isNeutral()) {
168
                $this->adjustmentsTotal += $adjustment->getAmount();
169
            }
170
        }
171
172
        $this->recalculateTotal();
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function recalculateUnitsTotal()
179
    {
180
        $this->unitsTotal = 0;
181
182
        foreach ($this->units as $unit) {
183
            $this->unitsTotal += $unit->getTotal();
184
        }
185
186
        $this->recalculateTotal();
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192
    public function equals(OrderItemInterface $orderItem)
193
    {
194
        return $this === $orderItem;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function isImmutable()
201
    {
202
        return $this->immutable;
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208
    public function setImmutable($immutable)
209
    {
210
        $this->immutable = (bool) $immutable;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function getUnits()
217
    {
218
        return $this->units;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224
    public function addUnit(OrderItemUnitInterface $unit)
225
    {
226
        if ($this !== $unit->getOrderItem()) {
227
            throw new \LogicException('This order item unit is assigned to a different order item.');
228
        }
229
230
        if (!$this->hasUnit($unit)) {
231
            $this->units->add($unit);
232
233
            $this->quantity++;
234
            $this->unitsTotal += $unit->getTotal();
235
            $this->recalculateTotal();
236
        }
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242
    public function removeUnit(OrderItemUnitInterface $unit)
243
    {
244
        if ($this->hasUnit($unit)) {
245
            $this->units->removeElement($unit);
246
247
            $this->quantity--;
248
            $this->unitsTotal -= $unit->getTotal();
249
            $this->recalculateTotal();
250
        }
251
    }
252
253
    /**
254
     * {@inheritdoc}
255
     */
256
    public function hasUnit(OrderItemUnitInterface $unit)
257
    {
258
        return $this->units->contains($unit);
259
    }
260
261
    /**
262
     * {@inheritdoc}
263
     */
264
    public function getAdjustments($type = null)
265
    {
266
        if (null === $type) {
267
            return $this->adjustments;
268
        }
269
270
        return $this->adjustments->filter(function (AdjustmentInterface $adjustment) use ($type) {
271
            return $type === $adjustment->getType();
272
        });
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278
    public function getAdjustmentsRecursively($type = null)
279
    {
280
        $adjustments = $this->getAdjustments($type)->toArray();
281
        foreach ($this->units as $unit) {
282
            $adjustments = array_merge($adjustments, $unit->getAdjustments($type)->toArray());
283
        }
284
285
        return $adjustments;
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291
    public function addAdjustment(AdjustmentInterface $adjustment)
292
    {
293
        if (!$this->hasAdjustment($adjustment)) {
294
            $this->adjustments->add($adjustment);
295
            $this->addToAdjustmentsTotal($adjustment);
296
            $adjustment->setAdjustable($this);
297
        }
298
    }
299
300
    /**
301
     * {@inheritdoc}
302
     */
303
    public function removeAdjustment(AdjustmentInterface $adjustment)
304
    {
305
        if (!$adjustment->isLocked() && $this->hasAdjustment($adjustment)) {
306
            $this->adjustments->removeElement($adjustment);
307
            $this->subtractFromAdjustmentsTotal($adjustment);
308
            $adjustment->setAdjustable(null);
309
        }
310
    }
311
312
    /**
313
     * {@inheritdoc}
314
     */
315
    public function hasAdjustment(AdjustmentInterface $adjustment)
316
    {
317
        return $this->adjustments->contains($adjustment);
318
    }
319
320
    /**
321
     * {@inheritdoc}
322
     */
323
    public function getAdjustmentsTotal($type = null)
324
    {
325
        if (null === $type) {
326
            return $this->adjustmentsTotal;
327
        }
328
329
        $total = 0;
330
        foreach ($this->getAdjustments($type) as $adjustment) {
331
            $total += $adjustment->getAmount();
332
        }
333
334
        return $total;
335
    }
336
337
    /**
338
     * {@inheritdoc}
339
     */
340
    public function getAdjustmentsTotalRecursively($type = null)
341
    {
342
        $total = $this->getAdjustmentsTotal($type);
343
        foreach ($this->units as $unit) {
344
            $total += $unit->getAdjustmentsTotal($type);
345
        }
346
347
        return $total;
348
    }
349
350
    /**
351
     * {@inheritdoc}
352
     */
353
    public function removeAdjustments($type)
354
    {
355
        foreach ($this->getAdjustments($type) as $adjustment) {
356
            if ($adjustment->isLocked()) {
357
                continue;
358
            }
359
360
            $this->removeAdjustment($adjustment);
361
        }
362
    }
363
364
    /**
365
     * {@inheritdoc}
366
     */
367
    public function removeAdjustmentsRecursively($type = null)
368
    {
369
        $this->removeAdjustments($type);
370
        foreach ($this->units as $unit) {
371
            $unit->removeAdjustments($type);
372
        }
373
    }
374
375
    /**
376
     * {@inheritdoc}
377
     */
378
    public function clearAdjustments()
379
    {
380
        $this->adjustments->clear();
381
        $this->recalculateAdjustmentsTotal();
382
    }
383
384
    /**
385
     *  Recalculates total after units total or adjustments total change.
386
     */
387
    protected function recalculateTotal()
388
    {
389
        $this->total = $this->unitsTotal + $this->adjustmentsTotal;
390
391
        if ($this->total < 0) {
392
            $this->total = 0;
393
        }
394
395
        if (null !== $this->order) {
396
            $this->order->recalculateItemsTotal();
397
        }
398
    }
399
400
    /**
401
     * @param AdjustmentInterface $adjustment
402
     */
403
    protected function addToAdjustmentsTotal(AdjustmentInterface $adjustment)
404
    {
405
        if (!$adjustment->isNeutral()) {
406
            $this->adjustmentsTotal += $adjustment->getAmount();
407
            $this->recalculateTotal();
408
        }
409
    }
410
411
    /**
412
     * @param AdjustmentInterface $adjustment
413
     */
414
    protected function subtractFromAdjustmentsTotal(AdjustmentInterface $adjustment)
415
    {
416
        if (!$adjustment->isNeutral()) {
417
            $this->adjustmentsTotal -= $adjustment->getAmount();
418
            $this->recalculateTotal();
419
        }
420
    }
421
}
422