Order   B
last analyzed

Complexity

Total Complexity 47

Size/Duplication

Total Lines 506
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 506
rs 8.439
c 0
b 0
f 0
wmc 47
lcom 3
cbo 3

39 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A getItems() 0 4 1
A setItems() 0 6 1
A countItems() 0 4 1
A getUser() 0 4 1
A setUser() 0 6 1
A addItem() 0 10 2
A removeItem() 0 8 2
A hasItem() 0 4 1
A getToPay() 0 4 1
A setToPay() 0 6 1
A getTotal() 0 4 1
A setTotal() 0 6 1
A getId() 0 4 1
A setId() 0 6 1
A getUpdatedAt() 0 4 1
A setUpdatedAt() 0 6 1
A getCreatedAt() 0 4 1
A setCreatedAt() 0 6 1
A getCurrency() 0 4 1
A setCurrency() 0 6 1
A getDiscountTotal() 0 4 1
A setDiscountTotal() 0 6 1
A addDiscount() 0 8 2
A hasDiscount() 0 4 1
A removeDiscount() 0 8 2
A getDiscounts() 0 4 1
A setDiscounts() 0 6 1
A calculateTotal() 0 10 2
A calculateItemsTotal() 0 15 2
A getItemsTotal() 0 4 1
A setItemsTotal() 0 6 1
A getPayments() 0 4 1
A getPaymentState() 0 4 1
A setPaymentState() 0 4 1
A addPayment() 0 8 2
A removePayment() 0 7 2
A hasPayment() 0 4 1
A getOrder() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Order often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Order, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @author Rafał Muszyński <[email protected]>
5
 * @copyright 2015 Sourcefabric z.ú.
6
 * @license http://www.gnu.org/licenses/gpl-3.0.txt
7
 */
8
9
namespace Newscoop\PaywallBundle\Entity;
10
11
use Doctrine\ORM\Mapping as ORM;
12
use Doctrine\Common\Collections\Collection;
13
use Doctrine\Common\Collections\ArrayCollection;
14
use Newscoop\Entity\User;
15
16
/**
17
 * Order entity.
18
 *
19
 * @ORM\Entity(repositoryClass="Newscoop\PaywallBundle\Entity\Repository\OrderRepository")
20
 * @ORM\Table(name="plugin_paywall_order")
21
 */
22
class Order implements OrderInterface
23
{
24
    /**
25
     * @ORM\Id
26
     * @ORM\GeneratedValue
27
     * @ORM\Column(type="integer", name="id")
28
     *
29
     * @var int
30
     */
31
    protected $id;
32
33
    /**
34
     * @ORM\OneToMany(targetEntity="UserSubscription", mappedBy="order", orphanRemoval=true, cascade={"all"})
35
     *
36
     * @var Collection
37
     */
38
    protected $items;
39
40
    /**
41
     * @ORM\Column(type="string", name="currency", length=3)
42
     *
43
     * @var string
44
     */
45
    protected $currency;
46
47
    /**
48
     * @ORM\Column(type="integer", name="total")
49
     *
50
     * @var int
51
     */
52
    protected $total = 0;
53
54
    /**
55
     * @ORM\Column(type="integer", name="items_total")
56
     *
57
     * @var int
58
     */
59
    protected $itemsTotal = 0;
60
61
    /**
62
     * @ORM\Column(type="integer", name="discount_total")
63
     *
64
     * @var int
65
     */
66
    protected $discountTotal = 0;
67
68
    /**
69
     * @ORM\ManyToOne(targetEntity="Newscoop\Entity\User")
70
     * @ORM\JoinColumn(name="user_id", referencedColumnName="Id")
71
     *
72
     * @var User
73
     */
74
    protected $user;
75
76
    /**
77
     * @ORM\OneToMany(targetEntity="Modification", mappedBy="order", orphanRemoval=true, cascade={"all"})
78
     *
79
     * @var Collection
80
     */
81
    protected $modifications;
82
83
    /**
84
     * @ORM\OneToMany(targetEntity="Payment", mappedBy="order", orphanRemoval=true, cascade={"all"})
85
     *
86
     * @var Collection
87
     */
88
    protected $payments;
89
90
    /**
91
     * @ORM\ManyToMany(targetEntity="Discount", cascade={"persist"})
92
     * @ORM\JoinTable(name="plugin_paywall_order_discount",
93
     *      joinColumns={
94
     *          @ORM\JoinColumn(name="order_id", referencedColumnName="id")
95
     *      },
96
     *      inverseJoinColumns={
97
     *          @ORM\JoinColumn(name="discount_id", referencedColumnName="id")
98
     *      }
99
     *  )
100
     *
101
     * @var Collection
102
     */
103
    protected $discounts;
104
105
    /**
106
     * @ORM\Column(type="string", name="payment_state")
107
     *
108
     * @var string
109
     */
110
    protected $paymentState = PaymentInterface::STATE_NEW;
111
112
    /**
113
     * @ORM\Column(type="datetime", name="updated_at", nullable=true)
114
     *
115
     * @var \DateTime
116
     */
117
    protected $updatedAt;
118
119
    /**
120
     * @ORM\Column(type="datetime", name="created_at")
121
     *
122
     * @var \DateTime
123
     */
124
    protected $createdAt;
125
126
    /**
127
     * Constructor.
128
     */
129
    public function __construct()
130
    {
131
        $this->items = new ArrayCollection();
132
        $this->modifications = new ArrayCollection();
133
        $this->payments = new ArrayCollection();
134
        $this->discounts = new ArrayCollection();
135
        $this->createdAt = new \DateTime();
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public function getItems()
142
    {
143
        return $this->items;
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function setItems(Collection $items)
150
    {
151
        $this->items = $items;
152
153
        return $this;
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159
    public function countItems()
160
    {
161
        return $this->items->count();
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function getUser()
168
    {
169
        return $this->user;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function setUser(User $user)
176
    {
177
        $this->user = $user;
178
179
        return $this;
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185
    public function addItem($item)
186
    {
187
        if ($this->hasItem($item)) {
188
            return $this;
189
        }
190
191
        $this->items->add($item);
192
193
        return $this;
194
    }
195
196
    /**
197
     * {@inheritdoc}
198
     */
199
    public function removeItem($item)
200
    {
201
        if ($this->hasItem($item)) {
202
            $this->items->removeElement($item);
203
        }
204
205
        return $this;
206
    }
207
208
    /**
209
     * {@inheritdoc}
210
     */
211
    public function hasItem($item)
212
    {
213
        return $this->items->contains($item);
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219
    public function getToPay()
220
    {
221
        return $this->getTotal();
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    public function setToPay($total)
228
    {
229
        $this->setTotal($total);
230
231
        return $this;
232
    }
233
234
    /**
235
     * Gets the value of total.
236
     *
237
     * @return int
238
     */
239
    public function getTotal()
240
    {
241
        return $this->total / 100;
242
    }
243
244
    /**
245
     * Sets the value of total.
246
     *
247
     * @param int $total the total
248
     *
249
     * @return self
250
     */
251
    public function setTotal($total)
252
    {
253
        $this->total = $total * 100;
254
255
        return $this;
256
    }
257
258
    /**
259
     * Gets the value of id.
260
     *
261
     * @return int
262
     */
263
    public function getId()
264
    {
265
        return $this->id;
266
    }
267
268
    /**
269
     * Sets the value of id.
270
     *
271
     * @param int $id the id
272
     *
273
     * @return self
274
     */
275
    public function setId($id)
276
    {
277
        $this->id = $id;
278
279
        return $this;
280
    }
281
282
    /**
283
     * Gets the value of updatedAt.
284
     *
285
     * @return \DateTime
286
     */
287
    public function getUpdatedAt()
288
    {
289
        return $this->updatedAt;
290
    }
291
292
    /**
293
     * Sets the value of updatedAt.
294
     *
295
     * @param \DateTime $updatedAt the updated at
296
     *
297
     * @return self
298
     */
299
    public function setUpdatedAt(\DateTime $updatedAt)
300
    {
301
        $this->updatedAt = $updatedAt;
302
303
        return $this;
304
    }
305
306
    /**
307
     * Gets the value of createdAt.
308
     *
309
     * @return \DateTime
310
     */
311
    public function getCreatedAt()
312
    {
313
        return $this->createdAt;
314
    }
315
316
    /**
317
     * Sets the value of createdAt.
318
     *
319
     * @param \DateTime $createdAt the created at
320
     *
321
     * @return self
322
     */
323
    public function setCreatedAt(\DateTime $createdAt)
324
    {
325
        $this->createdAt = $createdAt;
326
327
        return $this;
328
    }
329
330
    /**
331
     * Gets the value of currency.
332
     *
333
     * @return string
334
     */
335
    public function getCurrency()
336
    {
337
        return $this->currency;
338
    }
339
340
    /**
341
     * Sets the value of currency.
342
     *
343
     * @param string $currency the currency
344
     *
345
     * @return self
346
     */
347
    public function setCurrency($currency)
348
    {
349
        $this->currency = $currency;
350
351
        return $this;
352
    }
353
354
    /**
355
     * {@inheritdoc}
356
     */
357
    public function getDiscountTotal()
358
    {
359
        return $this->discountTotal / 100;
360
    }
361
362
    /**
363
     * {@inheritdoc}
364
     */
365
    public function setDiscountTotal($discountTotal)
366
    {
367
        $this->discountTotal = $discountTotal * 100;
368
369
        return $this;
370
    }
371
372
    public function addDiscount($discount)
373
    {
374
        if (!$this->hasDiscount($discount)) {
375
            $this->discounts->add($discount);
376
        }
377
378
        return $this;
379
    }
380
381
    public function hasDiscount($discount)
382
    {
383
        return $this->discounts->contains($discount);
384
    }
385
386
    public function removeDiscount($discount)
387
    {
388
        if ($this->hasDiscount($discount)) {
389
            $this->discounts->removeElement($discount);
390
        }
391
392
        return $this;
393
    }
394
395
    /**
396
     * Gets the discounts.
397
     *
398
     * @return Collection
399
     */
400
    public function getDiscounts()
401
    {
402
        return $this->discounts;
403
    }
404
405
    /**
406
     * Sets the discounts.
407
     *
408
     * @param Collection $discounts the discounts
409
     *
410
     * @return self
411
     */
412
    public function setDiscounts(Collection $discounts)
413
    {
414
        $this->discounts = $discounts;
415
416
        return $this;
417
    }
418
419
    /**
420
     * Calculates total order price including
421
     * all discounts.
422
     *
423
     * @return self
424
     */
425
    public function calculateTotal()
426
    {
427
        $this->calculateItemsTotal();
428
        $this->total = ($this->itemsTotal / 100 + $this->discountTotal / 100) * 100;
429
        if ($this->total < 0) {
430
            $this->total = 0;
431
        }
432
433
        return $this;
434
    }
435
436
    /**
437
     * Calculates all items discounts and unit prices.
438
     *
439
     * @return self
440
     */
441
    public function calculateItemsTotal()
442
    {
443
        $itemsTotal = 0;
444
        $this->discountTotal = 0;
445
        foreach ($this->items as $item) {
446
            $item->calculateToPay();
447
            $itemsTotal += $item->getToPay();
448
449
            $this->discountTotal -= $item->getDiscountTotal() * 100;
450
        }
451
452
        $this->itemsTotal = round($itemsTotal, 2) * 100;
0 ignored issues
show
Documentation Bug introduced by
The property $itemsTotal was declared of type integer, but round($itemsTotal, 2) * 100 is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
453
454
        return $this;
455
    }
456
457
    /**
458
     * Gets the value of itemsTotal.
459
     *
460
     * @return int
461
     */
462
    public function getItemsTotal()
463
    {
464
        return $this->itemsTotal / 100;
465
    }
466
467
    /**
468
     * Sets the value of itemsTotal.
469
     *
470
     * @param int $itemsTotal the items total
471
     *
472
     * @return self
473
     */
474
    public function setItemsTotal($itemsTotal)
475
    {
476
        $this->itemsTotal = $itemsTotal * 100;
477
478
        return $this;
479
    }
480
481
    /**
482
     * Gets the payments.
483
     *
484
     * @return Payment
485
     */
486
    public function getPayments()
487
    {
488
        return $this->payments;
489
    }
490
491
    public function getPaymentState()
492
    {
493
        return $this->paymentState;
494
    }
495
496
    public function setPaymentState($paymentState)
497
    {
498
        $this->paymentState = $paymentState;
499
    }
500
501
    public function addPayment(PaymentInterface $payment)
502
    {
503
        if (!$this->hasPayment($payment)) {
504
            $this->payments->add($payment);
505
            $payment->setOrder($this);
506
            $this->setPaymentState($payment->getState());
507
        }
508
    }
509
510
    public function removePayment(PaymentInterface $payment)
511
    {
512
        if ($this->hasPayment($payment)) {
513
            $this->payments->removeElement($payment);
514
            $payment->setOrder(null);
515
        }
516
    }
517
518
    public function hasPayment(PaymentInterface $payment)
519
    {
520
        return $this->payments->contains($payment);
521
    }
522
523
    public function getOrder()
524
    {
525
        return $this;
526
    }
527
}
528