Subscription   B
last analyzed

Complexity

Total Complexity 43

Size/Duplication

Total Lines 390
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 4

Importance

Changes 0
Metric Value
wmc 43
lcom 3
cbo 4
dl 0
loc 390
rs 8.96
c 0
b 0
f 0

35 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getId() 0 4 1
A getAmount() 0 4 1
A setAmount() 0 4 1
A getCurrencyCode() 0 4 1
A setCurrencyCode() 0 4 1
A getInterval() 0 4 1
A setInterval() 0 4 1
A getStartDate() 0 4 1
A setStartDate() 0 4 1
A getType() 0 4 1
A setType() 0 4 1
A getPurchaseCompletedAt() 0 4 1
A setPurchaseCompletedAt() 0 4 1
A completePurchase() 0 4 1
A getItems() 0 4 1
A clearItems() 0 6 1
A countItems() 0 4 1
A addItem() 0 10 2
A removeItem() 0 8 2
A hasItem() 0 4 1
A getItemsTotal() 0 4 1
A recalculateItemsTotal() 0 9 2
A recalculateTotal() 0 8 2
A getTotal() 0 4 1
A getTotalQuantity() 0 10 2
A isEmpty() 0 4 1
A getState() 0 4 1
A setState() 0 4 1
A getMetadata() 0 4 1
A setMetadata() 0 8 2
A hasMetadata() 0 4 1
A addMetadata() 0 8 2
A removeMetadata() 0 8 2
A hasSingleMetadata() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Subscription 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 Subscription, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace PH\Component\Subscription\Model;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection;
9
use Sylius\Component\Resource\Model\TimestampableTrait;
10
11
class Subscription implements SubscriptionInterface
12
{
13
    use TimestampableTrait;
14
15
    /**
16
     * @var mixed
17
     */
18
    protected $id;
19
20
    /**
21
     * @var int
22
     */
23
    protected $amount;
24
25
    /**
26
     * @var string|null
27
     */
28
    protected $number;
29
30
    /**
31
     * @var string
32
     */
33
    protected $currencyCode;
34
35
    /**
36
     * @var string|null
37
     */
38
    protected $interval;
39
40
    /**
41
     * @var \DateTimeInterface|null
42
     */
43
    protected $startDate;
44
45
    /**
46
     * @var string|null
47
     */
48
    protected $type = SubscriptionInterface::TYPE_NON_RECURRING;
49
50
    /**
51
     * @var Collection|SubscriptionItemInterface[]
52
     */
53
    protected $items;
54
55
    /**
56
     * @var \DateTimeInterface|null
57
     */
58
    protected $purchaseCompletedAt;
59
60
    /**
61
     * @var int
62
     */
63
    protected $itemsTotal = 0;
64
65
    /**
66
     * @var int
67
     */
68
    protected $total = 0;
69
70
    /**
71
     * @var string
72
     */
73
    protected $state = SubscriptionInterface::STATE_NEW;
74
75
    /**
76
     * @var Collection|MetadataInterface[]
77
     */
78
    protected $metadata;
79
80
    /**
81
     * Subscription constructor.
82
     */
83
    public function __construct()
84
    {
85
        $this->items = new ArrayCollection();
86
        $this->createdAt = new \DateTime();
87
        $this->metadata = new ArrayCollection();
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function getId()
94
    {
95
        return $this->id;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function getAmount(): ?int
102
    {
103
        return $this->amount;
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function setAmount(int $amount): void
110
    {
111
        $this->amount = $amount;
112
    }
113
114
    /**
115
     * {@inheritdoc}
116
     */
117
    public function getCurrencyCode(): ?string
118
    {
119
        return $this->currencyCode;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function setCurrencyCode(string $currencyCode)
126
    {
127
        $this->currencyCode = $currencyCode;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function getInterval(): ?string
134
    {
135
        return $this->interval;
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public function setInterval(?string $interval)
142
    {
143
        $this->interval = $interval;
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149
    public function getStartDate(): ?\DateTimeInterface
150
    {
151
        return $this->startDate;
152
    }
153
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function setStartDate(?\DateTimeInterface $startDate): void
158
    {
159
        $this->startDate = $startDate;
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function getType(): ?string
166
    {
167
        return $this->type;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function setType(?string $type): void
174
    {
175
        $this->type = $type;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function getPurchaseCompletedAt(): ?\DateTimeInterface
182
    {
183
        return $this->purchaseCompletedAt;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function setPurchaseCompletedAt(?\DateTimeInterface $purchaseCompletedAt): void
190
    {
191
        $this->purchaseCompletedAt = $purchaseCompletedAt;
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function completePurchase(): void
198
    {
199
        $this->purchaseCompletedAt = new \DateTime();
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    public function getItems(): Collection
206
    {
207
        return $this->items;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function clearItems(): void
214
    {
215
        $this->items->clear();
216
217
        $this->recalculateItemsTotal();
218
    }
219
220
    /**
221
     * {@inheritdoc}
222
     */
223
    public function countItems(): int
224
    {
225
        return $this->items->count();
226
    }
227
228
    /**
229
     * {@inheritdoc}
230
     */
231
    public function addItem(SubscriptionItemInterface $item): void
232
    {
233
        if ($this->hasItem($item)) {
234
            return;
235
        }
236
237
        $this->itemsTotal += $item->getTotal();
238
        $this->items->add($item);
239
        $item->setSubscription($this);
240
    }
241
242
    /**
243
     * {@inheritdoc}
244
     */
245
    public function removeItem(SubscriptionItemInterface $item): void
246
    {
247
        if ($this->hasItem($item)) {
248
            $this->items->removeElement($item);
249
            $this->itemsTotal -= $item->getTotal();
250
            $item->setSubscription(null);
251
        }
252
    }
253
254
    /**
255
     * {@inheritdoc}
256
     */
257
    public function hasItem(SubscriptionItemInterface $item): bool
258
    {
259
        return $this->items->contains($item);
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function getItemsTotal(): int
266
    {
267
        return $this->itemsTotal;
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273
    public function recalculateItemsTotal(): void
274
    {
275
        $this->itemsTotal = 0;
276
        foreach ($this->items as $item) {
277
            $this->itemsTotal += $item->getTotal();
278
        }
279
280
        $this->recalculateTotal();
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    protected function recalculateTotal(): void
287
    {
288
        $this->total = $this->itemsTotal;
289
290
        if ($this->total < 0) {
291
            $this->total = 0;
292
        }
293
    }
294
295
    /**
296
     * {@inheritdoc}
297
     */
298
    public function getTotal(): int
299
    {
300
        return $this->total;
301
    }
302
303
    /**
304
     * {@inheritdoc}
305
     */
306
    public function getTotalQuantity(): int
307
    {
308
        $quantity = 0;
309
310
        foreach ($this->items as $item) {
311
            $quantity += $item->getQuantity();
312
        }
313
314
        return $quantity;
315
    }
316
317
    /**
318
     * {@inheritdoc}
319
     */
320
    public function isEmpty(): bool
321
    {
322
        return $this->items->isEmpty();
323
    }
324
325
    /**
326
     * {@inheritdoc}
327
     */
328
    public function getState(): string
329
    {
330
        return $this->state;
331
    }
332
333
    /**
334
     * {@inheritdoc}
335
     */
336
    public function setState(string $state): void
337
    {
338
        $this->state = $state;
339
    }
340
341
    /**
342
     * {@inheritdoc}
343
     */
344
    public function getMetadata(): Collection
345
    {
346
        return $this->metadata;
347
    }
348
349
    /**
350
     * {@inheritdoc}
351
     */
352
    public function setMetadata(Collection $metadata): void
353
    {
354
        foreach ($metadata as $item) {
355
            $item->setSubscription($this);
356
        }
357
358
        $this->metadata = $metadata;
359
    }
360
361
    /**
362
     * {@inheritdoc}
363
     */
364
    public function hasMetadata(): bool
365
    {
366
        return !$this->metadata->isEmpty();
367
    }
368
369
    /**
370
     * {@inheritdoc}
371
     */
372
    public function addMetadata(MetadataInterface $metadata): void
373
    {
374
        /** @var MetadataInterface $metadata */
375
        if (!$this->hasSingleMetadata($metadata)) {
376
            $this->metadata->add($metadata);
377
            $metadata->setSubscription($this);
378
        }
379
    }
380
381
    /**
382
     * {@inheritdoc}
383
     */
384
    public function removeMetadata(MetadataInterface $metadata): void
385
    {
386
        /** @var MetadataInterface $metadata */
387
        if ($this->hasSingleMetadata($metadata)) {
388
            $this->metadata->removeElement($metadata);
389
            $metadata->setSubscription(null);
390
        }
391
    }
392
393
    /**
394
     * {@inheritdoc}
395
     */
396
    public function hasSingleMetadata(MetadataInterface $metadata): bool
397
    {
398
        return $this->metadata->contains($metadata);
399
    }
400
}
401