Completed
Push — master ( d81c19...f57266 )
by Kamil
20s
created

src/Sylius/Component/Order/Model/OrderItem.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
declare(strict_types=1);
13
14
namespace Sylius\Component\Order\Model;
15
16
use Doctrine\Common\Collections\ArrayCollection;
17
use Doctrine\Common\Collections\Collection;
18
19
class OrderItem implements OrderItemInterface
20
{
21
    /**
22
     * @var mixed
23
     */
24
    protected $id;
25
26
    /**
27
     * @var OrderInterface|null
28
     */
29
    protected $order;
30
31
    /**
32
     * @var int
33
     */
34
    protected $quantity = 0;
35
36
    /**
37
     * @var int
38
     */
39
    protected $unitPrice = 0;
40
41
    /**
42
     * @var int
43
     */
44
    protected $total = 0;
45
46
    /**
47
     * @var bool
48
     */
49
    protected $immutable = false;
50
51
    /**
52
     * @var Collection|OrderItemUnitInterface[]
53
     */
54
    protected $units;
55
56
    /**
57
     * @var int
58
     */
59
    protected $unitsTotal = 0;
60
61
    /**
62
     * @var Collection|AdjustmentInterface[]
63
     */
64
    protected $adjustments;
65
66
    /**
67
     * @var int
68
     */
69
    protected $adjustmentsTotal = 0;
70
71
    public function __construct()
72
    {
73
        $this->adjustments = new ArrayCollection();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Doctrine\Common\Collections\ArrayCollection() of type object<Doctrine\Common\C...ctions\ArrayCollection> is incompatible with the declared type object<Doctrine\Common\C...l\AdjustmentInterface>> of property $adjustments.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
74
        $this->units = new ArrayCollection();
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function getId()
81
    {
82
        return $this->id;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function getQuantity(): int
89
    {
90
        return $this->quantity;
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function getOrder(): ?OrderInterface
97
    {
98
        return $this->order;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function setOrder(?OrderInterface $order): void
105
    {
106
        $currentOrder = $this->getOrder();
107
        if ($currentOrder === $order) {
108
            return;
109
        }
110
111
        $this->order = null;
112
113
        if (null !== $currentOrder) {
114
            $currentOrder->removeItem($this);
115
        }
116
117
        if (null === $order) {
118
            return;
119
        }
120
121
        $this->order = $order;
122
123
        if (!$order->hasItem($this)) {
124
            $order->addItem($this);
125
        }
126
    }
127
128
    /**
129
     * {@inheritdoc}
130
     */
131
    public function getUnitPrice(): int
132
    {
133
        return $this->unitPrice;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139
    public function setUnitPrice(int $unitPrice): void
140
    {
141
        $this->unitPrice = $unitPrice;
142
        $this->recalculateUnitsTotal();
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function getTotal(): int
149
    {
150
        return $this->total;
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function recalculateAdjustmentsTotal(): void
157
    {
158
        $this->adjustmentsTotal = 0;
159
160
        foreach ($this->adjustments as $adjustment) {
161
            if (!$adjustment->isNeutral()) {
162
                $this->adjustmentsTotal += $adjustment->getAmount();
163
            }
164
        }
165
166
        $this->recalculateTotal();
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function recalculateUnitsTotal(): void
173
    {
174
        $this->unitsTotal = 0;
175
176
        foreach ($this->units as $unit) {
177
            $this->unitsTotal += $unit->getTotal();
178
        }
179
180
        $this->recalculateTotal();
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function equals(OrderItemInterface $orderItem): bool
187
    {
188
        return $this === $orderItem;
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function isImmutable(): bool
195
    {
196
        return $this->immutable;
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202
    public function setImmutable(bool $immutable): void
203
    {
204
        $this->immutable = $immutable;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    public function getUnits(): Collection
211
    {
212
        return $this->units;
213
    }
214
215
    /**
216
     * {@inheritdoc}
217
     */
218
    public function addUnit(OrderItemUnitInterface $unit): void
219
    {
220
        if ($this !== $unit->getOrderItem()) {
221
            throw new \LogicException('This order item unit is assigned to a different order item.');
222
        }
223
224
        if (!$this->hasUnit($unit)) {
225
            $this->units->add($unit);
226
227
            ++$this->quantity;
228
            $this->unitsTotal += $unit->getTotal();
229
            $this->recalculateTotal();
230
        }
231
    }
232
233
    /**
234
     * {@inheritdoc}
235
     */
236
    public function removeUnit(OrderItemUnitInterface $unit): void
237
    {
238
        if ($this->hasUnit($unit)) {
239
            $this->units->removeElement($unit);
240
241
            --$this->quantity;
242
            $this->unitsTotal -= $unit->getTotal();
243
            $this->recalculateTotal();
244
        }
245
    }
246
247
    /**
248
     * {@inheritdoc}
249
     */
250
    public function hasUnit(OrderItemUnitInterface $unit): bool
251
    {
252
        return $this->units->contains($unit);
253
    }
254
255
    /**
256
     * {@inheritdoc}
257
     */
258
    public function getAdjustments(?string $type = null): Collection
259
    {
260
        if (null === $type) {
261
            return $this->adjustments;
262
        }
263
264
        return $this->adjustments->filter(function (AdjustmentInterface $adjustment) use ($type) {
265
            return $type === $adjustment->getType();
266
        });
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272
    public function getAdjustmentsRecursively(?string $type = null): Collection
273
    {
274
        $adjustments = clone $this->getAdjustments($type);
275
276
        foreach ($this->units as $unit) {
277
            foreach ($unit->getAdjustments($type) as $adjustment) {
278
                $adjustments->add($adjustment);
279
            }
280
        }
281
282
        return $adjustments;
283
    }
284
285
    /**
286
     * {@inheritdoc}
287
     */
288
    public function addAdjustment(AdjustmentInterface $adjustment): void
289
    {
290
        if (!$this->hasAdjustment($adjustment)) {
291
            $this->adjustments->add($adjustment);
292
            $this->addToAdjustmentsTotal($adjustment);
293
            $adjustment->setAdjustable($this);
294
        }
295
    }
296
297
    /**
298
     * {@inheritdoc}
299
     */
300
    public function removeAdjustment(AdjustmentInterface $adjustment): void
301
    {
302
        if (!$adjustment->isLocked() && $this->hasAdjustment($adjustment)) {
303
            $this->adjustments->removeElement($adjustment);
304
            $this->subtractFromAdjustmentsTotal($adjustment);
305
            $adjustment->setAdjustable(null);
306
        }
307
    }
308
309
    /**
310
     * {@inheritdoc}
311
     */
312
    public function hasAdjustment(AdjustmentInterface $adjustment): bool
313
    {
314
        return $this->adjustments->contains($adjustment);
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320
    public function getAdjustmentsTotal(?string $type = null): int
321
    {
322
        if (null === $type) {
323
            return $this->adjustmentsTotal;
324
        }
325
326
        $total = 0;
327
        foreach ($this->getAdjustments($type) as $adjustment) {
328
            if (!$adjustment->isNeutral()) {
329
                $total += $adjustment->getAmount();
330
            }
331
        }
332
333
        return $total;
334
    }
335
336
    /**
337
     * {@inheritdoc}
338
     */
339
    public function getAdjustmentsTotalRecursively(?string $type = null): int
340
    {
341
        $total = 0;
342
343
        foreach ($this->getAdjustmentsRecursively($type) as $adjustment) {
344
            if (!$adjustment->isNeutral()) {
345
                $total += $adjustment->getAmount();
346
            }
347
        }
348
349
        return $total;
350
    }
351
352
    /**
353
     * {@inheritdoc}
354
     */
355
    public function removeAdjustments(?string $type = null): void
356
    {
357
        foreach ($this->getAdjustments($type) as $adjustment) {
358
            $this->removeAdjustment($adjustment);
359
        }
360
    }
361
362
    /**
363
     * {@inheritdoc}
364
     */
365
    public function removeAdjustmentsRecursively(?string $type = null): void
366
    {
367
        $this->removeAdjustments($type);
368
        foreach ($this->units as $unit) {
369
            $unit->removeAdjustments($type);
370
        }
371
    }
372
373
    /**
374
     * Recalculates total after units total or adjustments total change.
375
     */
376
    protected function recalculateTotal(): void
377
    {
378
        $this->total = $this->unitsTotal + $this->adjustmentsTotal;
379
380
        if ($this->total < 0) {
381
            $this->total = 0;
382
        }
383
384
        if (null !== $this->order) {
385
            $this->order->recalculateItemsTotal();
386
        }
387
    }
388
389
    /**
390
     * @param AdjustmentInterface $adjustment
391
     */
392
    protected function addToAdjustmentsTotal(AdjustmentInterface $adjustment): void
393
    {
394
        if (!$adjustment->isNeutral()) {
395
            $this->adjustmentsTotal += $adjustment->getAmount();
396
            $this->recalculateTotal();
397
        }
398
    }
399
400
    /**
401
     * @param AdjustmentInterface $adjustment
402
     */
403
    protected function subtractFromAdjustmentsTotal(AdjustmentInterface $adjustment): void
404
    {
405
        if (!$adjustment->isNeutral()) {
406
            $this->adjustmentsTotal -= $adjustment->getAmount();
407
            $this->recalculateTotal();
408
        }
409
    }
410
}
411