Passed
Push — main ( ed7362...5e204e )
by Iain
04:54
created

Subscription   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 81
c 7
b 0
f 0
dl 0
loc 307
rs 7.92
wmc 51

50 Methods

Rating   Name   Duplication   Size   Complexity  
A setTrialLengthDays() 0 3 1
A setStartOfCurrentPeriod() 0 3 1
A getTrialLengthDays() 0 3 1
A getStartOfCurrentPeriod() 0 3 1
A isHasTrial() 0 3 1
A setHasTrial() 0 3 1
A getMoneyAmount() 0 3 1
A getValidUntil() 0 3 1
A setCurrency() 0 3 1
A getEndedAt() 0 3 1
A setPaymentDetails() 0 3 1
A setCreatedAt() 0 3 1
A setPrice() 0 3 1
A getUpdatedAt() 0 3 1
A setValidUntil() 0 3 1
A setUpdatedAt() 0 3 1
A getAmount() 0 3 1
A setMainExternalReference() 0 3 1
A getPrice() 0 3 1
A setMainExternalReferenceDetailsUrl() 0 3 1
A getCreatedAt() 0 3 1
A setCustomer() 0 3 1
A getMainExternalReferenceDetailsUrl() 0 3 1
A setMoneyAmount() 0 8 2
A getSubscriptionPlan() 0 3 1
A setEndedAt() 0 3 1
A getCurrency() 0 3 1
A getPaymentDetails() 0 3 1
A isActive() 0 3 1
A setActive() 0 3 1
A setChildExternalReference() 0 3 1
A endAtEndOfPeriod() 0 3 1
A setAmount() 0 3 1
A getCustomer() 0 3 1
A getMainExternalReference() 0 3 1
A setSubscriptionPlan() 0 3 1
A getChildExternalReference() 0 3 1
A endNow() 0 4 1
A getPaymentSchedule() 0 3 1
A getStatus() 0 3 1
A getSeats() 0 3 1
A setId() 0 3 1
A setPlanName() 0 3 1
A getPlanName() 0 3 1
A setSeats() 0 3 1
A getId() 0 3 1
A setPaymentSchedule() 0 3 1
A setStatus() 0 8 1
A setPayments() 0 3 1
A getPayments() 0 3 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.

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
/*
6
 * Copyright (C) 2020-2024 Iain Cambridge
7
 *
8
 *     This program is free software: you can redistribute it and/or modify
9
 *     it under the terms of the GNU General Public License as published by
10
 *     the Free Software Foundation, either version 3 of the License, or
11
 *     (at your option) any later version.
12
 *
13
 *     This program is distributed in the hope that it will be useful,
14
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *     GNU General Public License for more details.
17
 *
18
 *     You should have received a copy of the GNU General Public License
19
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace Parthenon\Billing\Entity;
23
24
use Brick\Money\Currency;
25
use Brick\Money\Money;
26
use Doctrine\Common\Collections\Collection;
27
use Parthenon\Billing\Enum\SubscriptionStatus;
28
29
class Subscription implements SubscriptionInterface
30
{
31
    private $id;
32
33
    private CustomerInterface $customer;
34
35
    private string $planName;
36
37
    private ?string $paymentSchedule = null;
38
39
    private ?int $seats = 1;
40
41
    private bool $active;
42
43
    private SubscriptionStatus $status;
44
45
    private ?int $amount = null;
46
47
    private ?string $currency = null;
48
49
    private ?string $mainExternalReference = null;
50
51
    private ?string $mainExternalReferenceDetailsUrl = null;
52
53
    private ?string $childExternalReference = null;
54
55
    private ?PaymentCard $paymentDetails = null;
56
57
    private ?SubscriptionPlanInterface $subscriptionPlan = null;
58
59
    private ?PriceInterface $price = null;
60
61
    private \DateTime $createdAt;
62
63
    private ?\DateTime $startOfCurrentPeriod = null;
64
65
    private ?\DateTime $validUntil = null;
66
67
    private \DateTime $updatedAt;
68
69
    private ?\DateTime $endedAt = null;
70
71
    private bool $hasTrial = false;
72
73
    private ?int $trialLengthDays = 0;
74
75
    private Collection $payments;
76
77
    public function getId()
78
    {
79
        return $this->id;
80
    }
81
82
    public function setId($id): void
83
    {
84
        $this->id = $id;
85
    }
86
87
    public function getPlanName(): string
88
    {
89
        return $this->planName;
90
    }
91
92
    public function setPlanName(string $planName): void
93
    {
94
        $this->planName = $planName;
95
    }
96
97
    public function getPaymentSchedule(): ?string
98
    {
99
        return $this->paymentSchedule;
100
    }
101
102
    public function setPaymentSchedule(?string $paymentSchedule): void
103
    {
104
        $this->paymentSchedule = $paymentSchedule;
105
    }
106
107
    public function getSeats(): ?int
108
    {
109
        return $this->seats;
110
    }
111
112
    public function setSeats(?int $seats): void
113
    {
114
        $this->seats = $seats;
115
    }
116
117
    public function getStatus(): SubscriptionStatus
118
    {
119
        return $this->status;
120
    }
121
122
    public function setStatus(SubscriptionStatus $status): void
123
    {
124
        $this->active = match ($status) {
125
            SubscriptionStatus::ACTIVE, SubscriptionStatus::TRIAL_ACTIVE, SubscriptionStatus::OVERDUE_PAYMENT_OPEN, SubscriptionStatus::PENDING_CANCEL => true,
126
            default => false,
127
        };
128
129
        $this->status = $status;
130
    }
131
132
    public function getSubscriptionPlan(): ?SubscriptionPlan
133
    {
134
        return $this->subscriptionPlan;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->subscriptionPlan could return the type Parthenon\Billing\Entity\SubscriptionPlanInterface which includes types incompatible with the type-hinted return Parthenon\Billing\Entity\SubscriptionPlan|null. Consider adding an additional type-check to rule them out.
Loading history...
135
    }
136
137
    public function setSubscriptionPlan(?SubscriptionPlan $subscriptionPlan): void
138
    {
139
        $this->subscriptionPlan = $subscriptionPlan;
140
    }
141
142
    public function getMainExternalReference(): ?string
143
    {
144
        return $this->mainExternalReference;
145
    }
146
147
    public function setMainExternalReference(?string $mainExternalReference): void
148
    {
149
        $this->mainExternalReference = $mainExternalReference;
150
    }
151
152
    public function getChildExternalReference(): ?string
153
    {
154
        return $this->childExternalReference;
155
    }
156
157
    public function setChildExternalReference(?string $childExternalReference): void
158
    {
159
        $this->childExternalReference = $childExternalReference;
160
    }
161
162
    public function getAmount(): ?int
163
    {
164
        return $this->amount;
165
    }
166
167
    public function setAmount(?int $amount): void
168
    {
169
        $this->amount = $amount;
170
    }
171
172
    public function getCurrency(): ?string
173
    {
174
        return $this->currency;
175
    }
176
177
    public function setCurrency(?string $currency): void
178
    {
179
        $this->currency = $currency;
180
    }
181
182
    public function getPrice(): ?Price
183
    {
184
        return $this->price;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->price could return the type Parthenon\Billing\Entity\PriceInterface which includes types incompatible with the type-hinted return Parthenon\Billing\Entity\Price|null. Consider adding an additional type-check to rule them out.
Loading history...
185
    }
186
187
    public function setPrice(?Price $price): void
188
    {
189
        $this->price = $price;
190
    }
191
192
    public function getCreatedAt(): \DateTimeInterface
193
    {
194
        return $this->createdAt;
195
    }
196
197
    public function setCreatedAt(\DateTimeInterface $createdAt): void
198
    {
199
        $this->createdAt = $createdAt;
200
    }
201
202
    public function getUpdatedAt(): \DateTimeInterface
203
    {
204
        return $this->updatedAt;
205
    }
206
207
    public function setUpdatedAt(\DateTimeInterface $updatedAt): void
208
    {
209
        $this->updatedAt = $updatedAt;
210
    }
211
212
    public function getEndedAt(): ?\DateTimeInterface
213
    {
214
        return $this->endedAt;
215
    }
216
217
    public function setEndedAt(?\DateTimeInterface $endedAt): void
218
    {
219
        $this->endedAt = $endedAt;
220
    }
221
222
    public function endAtEndOfPeriod(): void
223
    {
224
        $this->endedAt = clone $this->validUntil;
225
    }
226
227
    public function endNow(): void
228
    {
229
        $this->endedAt = new \DateTime('now');
230
        $this->validUntil = new \DateTime('now');
231
    }
232
233
    public function isActive(): bool
234
    {
235
        return $this->active;
236
    }
237
238
    public function setActive(bool $active): void
239
    {
240
        $this->active = $active;
241
    }
242
243
    public function getValidUntil(): ?\DateTime
244
    {
245
        return $this->validUntil;
246
    }
247
248
    public function setValidUntil(\DateTime $validUntil): void
249
    {
250
        $this->validUntil = $validUntil;
251
    }
252
253
    public function getMoneyAmount(): Money
254
    {
255
        return Money::ofMinor($this->amount, Currency::of($this->currency));
256
    }
257
258
    public function setMoneyAmount(?Money $money)
259
    {
260
        if (!$money) {
261
            return;
262
        }
263
264
        $this->amount = $money->getMinorAmount()->toInt();
265
        $this->currency = $money->getCurrency()->getCurrencyCode();
266
    }
267
268
    public function getCustomer(): CustomerInterface
269
    {
270
        return $this->customer;
271
    }
272
273
    public function setCustomer(CustomerInterface $customer): void
274
    {
275
        $this->customer = $customer;
276
    }
277
278
    public function getMainExternalReferenceDetailsUrl(): ?string
279
    {
280
        return $this->mainExternalReferenceDetailsUrl;
281
    }
282
283
    public function setMainExternalReferenceDetailsUrl(?string $mainExternalReferenceDetailsUrl): void
284
    {
285
        $this->mainExternalReferenceDetailsUrl = $mainExternalReferenceDetailsUrl;
286
    }
287
288
    public function getStartOfCurrentPeriod(): ?\DateTimeInterface
289
    {
290
        return $this->startOfCurrentPeriod;
291
    }
292
293
    public function setStartOfCurrentPeriod(?\DateTimeInterface $startOfCurrentPeriod): void
294
    {
295
        $this->startOfCurrentPeriod = $startOfCurrentPeriod;
296
    }
297
298
    public function isHasTrial(): bool
299
    {
300
        return $this->hasTrial;
301
    }
302
303
    public function setHasTrial(bool $hasTrial): void
304
    {
305
        $this->hasTrial = $hasTrial;
306
    }
307
308
    public function getTrialLengthDays(): ?int
309
    {
310
        return $this->trialLengthDays;
311
    }
312
313
    public function setTrialLengthDays(?int $trialLengthDays): void
314
    {
315
        $this->trialLengthDays = $trialLengthDays;
316
    }
317
318
    public function getPaymentDetails(): ?PaymentCard
319
    {
320
        return $this->paymentDetails;
321
    }
322
323
    public function setPaymentDetails(?PaymentCard $paymentDetails): void
324
    {
325
        $this->paymentDetails = $paymentDetails;
326
    }
327
328
    public function getPayments(): Collection
329
    {
330
        return $this->payments;
331
    }
332
333
    public function setPayments(Collection $payments): void
334
    {
335
        $this->payments = $payments;
336
    }
337
}
338