Complex classes like Invoice 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 Invoice, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | final class Invoice implements CreatableFromArray, ContainsMetadata |
||
23 | { |
||
24 | use LivemodeTrait; |
||
25 | use MetadataTrait; |
||
26 | |||
27 | const BILLING_CHARGE_AUTOMATICALLY = 'charge_automatically'; |
||
28 | const BILLING_SEND_INVOICE = 'send_invoice'; |
||
29 | |||
30 | const BILLING_REASON_SUBSCRIPTION_CYCLE = 'subscription_cycle'; |
||
31 | const BILLING_REASON_SUBSCRIPTION_CREATE = 'subscription_create'; |
||
32 | const BILLING_REASON_SUBSCRIPTION_UPDATE = 'subscription_update'; |
||
33 | const BILLING_REASON_SUBSCRIPTION = 'subscription'; |
||
34 | const BILLING_REASON_MANUAL = 'manual'; |
||
35 | const BILLING_REASON_UPCOMING = 'upcoming'; |
||
36 | const BILLING_REASON_SUBSCRIPTION_THRESHOLD = 'subscription_threshold'; |
||
37 | |||
38 | const STATUS_DRAFT = 'draft'; |
||
39 | const STATUS_OPEN = 'open'; |
||
40 | const STATUS_PAID = 'paid'; |
||
41 | const STATUS_UNCOLLECTIBLE = 'uncollectible'; |
||
42 | const STATUS_VOID = 'void'; |
||
43 | |||
44 | /** |
||
45 | * @var ?string |
||
46 | */ |
||
47 | private $id; |
||
48 | |||
49 | /** |
||
50 | * @var Money |
||
51 | */ |
||
52 | private $amountDue; |
||
53 | |||
54 | /** |
||
55 | * @var Money |
||
56 | */ |
||
57 | private $amountPaid; |
||
58 | |||
59 | /** |
||
60 | * @var Money |
||
61 | */ |
||
62 | private $amountRemaining; |
||
63 | |||
64 | /** |
||
65 | * @var ?Money |
||
66 | */ |
||
67 | private $applicationFeeAmount; |
||
68 | |||
69 | /** |
||
70 | * @var int |
||
71 | */ |
||
72 | private $attemptCount; |
||
73 | |||
74 | /** |
||
75 | * @var bool |
||
76 | */ |
||
77 | private $attempted; |
||
78 | |||
79 | /** |
||
80 | * @var bool |
||
81 | */ |
||
82 | private $autoAdvance; |
||
83 | |||
84 | /** |
||
85 | * @var string |
||
86 | */ |
||
87 | private $billing; |
||
88 | |||
89 | /** |
||
90 | * @var string |
||
91 | */ |
||
92 | private $billingReason; |
||
93 | |||
94 | /** |
||
95 | * @var ?string |
||
96 | */ |
||
97 | private $charge; |
||
98 | |||
99 | /** |
||
100 | * @var \DateTimeImmutable |
||
101 | */ |
||
102 | private $createdAt; |
||
103 | |||
104 | /** |
||
105 | * @var Currency |
||
106 | */ |
||
107 | private $currency; |
||
108 | |||
109 | /** |
||
110 | * @var array |
||
111 | */ |
||
112 | private $customFields; |
||
113 | |||
114 | /** |
||
115 | * @var string |
||
116 | */ |
||
117 | private $customer; |
||
118 | |||
119 | /** |
||
120 | * @var ?string |
||
121 | */ |
||
122 | private $defaultSource; |
||
123 | |||
124 | /** |
||
125 | * @var string |
||
126 | */ |
||
127 | private $description; |
||
128 | |||
129 | /** |
||
130 | * @var ?Discount |
||
131 | */ |
||
132 | private $discount; |
||
133 | |||
134 | /** |
||
135 | * @var ?\DateTimeImmutable |
||
136 | */ |
||
137 | private $dueAt; |
||
138 | |||
139 | /** |
||
140 | * @var ?Money |
||
141 | */ |
||
142 | private $endingBalance; |
||
143 | |||
144 | /** |
||
145 | * @var ?string |
||
146 | */ |
||
147 | private $footer; |
||
148 | |||
149 | /** |
||
150 | * @var ?string |
||
151 | */ |
||
152 | private $hostedInvoiceUrl; |
||
153 | |||
154 | /** |
||
155 | * @var ?string |
||
156 | */ |
||
157 | private $invoicePdf; |
||
158 | |||
159 | /** |
||
160 | * @var LineItemCollection |
||
161 | */ |
||
162 | private $lines; |
||
163 | |||
164 | /** |
||
165 | * @var ?\DateTimeImmutable |
||
166 | */ |
||
167 | private $nextPaymentAttempt; |
||
168 | |||
169 | /** |
||
170 | * @var string |
||
171 | */ |
||
172 | private $number; |
||
173 | |||
174 | /** |
||
175 | * @var bool |
||
176 | */ |
||
177 | private $paid; |
||
178 | |||
179 | /** |
||
180 | * @var ?string |
||
181 | */ |
||
182 | private $paymentIntentId; |
||
183 | |||
184 | /** |
||
185 | * @var \DateTimeImmutable |
||
186 | */ |
||
187 | private $periodEndAt; |
||
188 | |||
189 | /** |
||
190 | * @var \DateTimeImmutable |
||
191 | */ |
||
192 | private $periodStartAt; |
||
193 | |||
194 | /** |
||
195 | * @var ?string |
||
196 | */ |
||
197 | private $receiptNumber; |
||
198 | |||
199 | /** |
||
200 | * @var Money |
||
201 | */ |
||
202 | private $startingBalance; |
||
203 | |||
204 | /** |
||
205 | * @var ?string |
||
206 | */ |
||
207 | private $statementDescriptor; |
||
208 | |||
209 | /** |
||
210 | * @var string |
||
211 | */ |
||
212 | private $status; |
||
213 | |||
214 | /** |
||
215 | * @var string |
||
216 | */ |
||
217 | private $subscription; |
||
218 | |||
219 | /** |
||
220 | * @var ?\DateTimeImmutable |
||
221 | */ |
||
222 | private $subscriptionProrationAt; |
||
223 | |||
224 | /** |
||
225 | * @var Money |
||
226 | */ |
||
227 | private $subtotal; |
||
228 | |||
229 | /** |
||
230 | * @var Money |
||
231 | */ |
||
232 | private $tax; |
||
233 | |||
234 | /** |
||
235 | * @var float |
||
236 | */ |
||
237 | private $taxPercent; |
||
238 | |||
239 | /** |
||
240 | * @var ?ThresholdReason |
||
241 | */ |
||
242 | private $thresholdReason; |
||
243 | |||
244 | /** |
||
245 | * @var Money |
||
246 | */ |
||
247 | private $total; |
||
248 | |||
249 | /** |
||
250 | * @var ?\DateTimeImmutable |
||
251 | */ |
||
252 | private $webhooksDeliveredAt; |
||
253 | |||
254 | 11 | public static function createFromArray(array $data): self |
|
313 | |||
314 | 1 | public function getId(): ?string |
|
318 | |||
319 | 1 | public function getAmountDue(): Money |
|
323 | |||
324 | 1 | public function getAmountPaid(): Money |
|
328 | |||
329 | 1 | public function getAmountRemaining(): Money |
|
333 | |||
334 | 1 | public function getApplicationFeeAmount(): ?Money |
|
338 | |||
339 | 1 | public function getAttemptCount(): int |
|
343 | |||
344 | 1 | public function isAttempted(): bool |
|
348 | |||
349 | 1 | public function isAutoAdvance(): bool |
|
353 | |||
354 | 1 | public function getBilling(): string |
|
358 | |||
359 | 1 | public function getBillingReason(): string |
|
363 | |||
364 | 1 | public function getCharge(): ?string |
|
368 | |||
369 | 1 | public function getCreatedAt(): \DateTimeImmutable |
|
373 | |||
374 | 1 | public function getCurrency(): Currency |
|
378 | |||
379 | 1 | public function getCustomFields(): array |
|
383 | |||
384 | 1 | public function getCustomer(): string |
|
388 | |||
389 | 1 | public function getDefaultSource(): ?string |
|
393 | |||
394 | 1 | public function getDescription(): ?string |
|
398 | |||
399 | 1 | public function getDiscount(): ?Discount |
|
403 | |||
404 | 1 | public function getDueAt(): ?\DateTimeImmutable |
|
408 | |||
409 | 1 | public function getEndingBalance(): ?Money |
|
413 | |||
414 | 1 | public function getFooter(): ?string |
|
418 | |||
419 | 1 | public function getHostedInvoiceUrl(): ?string |
|
423 | |||
424 | 1 | public function getInvoicePdf(): ?string |
|
428 | |||
429 | 1 | public function getLines(): LineItemCollection |
|
433 | |||
434 | 1 | public function getNextPaymentAttempt(): ?\DateTimeImmutable |
|
438 | |||
439 | 1 | public function getNumber(): string |
|
443 | |||
444 | 1 | public function isPaid(): bool |
|
448 | |||
449 | 1 | public function getPaymentIntentId(): ?string |
|
453 | |||
454 | 1 | public function getPeriodEndAt(): \DateTimeImmutable |
|
458 | |||
459 | 1 | public function getPeriodStartAt(): \DateTimeImmutable |
|
463 | |||
464 | 1 | public function getReceiptNumber(): ?string |
|
468 | |||
469 | 1 | public function getStartingBalance(): Money |
|
473 | |||
474 | 1 | public function getStatementDescriptor(): ?string |
|
478 | |||
479 | 1 | public function getStatus(): string |
|
483 | |||
484 | 1 | public function getSubscription(): ?string |
|
488 | |||
489 | 1 | public function getSubscriptionProrationAt(): ?\DateTimeImmutable |
|
493 | |||
494 | 1 | public function getSubtotal(): Money |
|
498 | |||
499 | 1 | public function getTax(): Money |
|
503 | |||
504 | 1 | public function getTaxPercent(): float |
|
508 | |||
509 | 1 | public function getThresholdReason(): ?ThresholdReason |
|
513 | |||
514 | 1 | public function getTotal(): Money |
|
518 | |||
519 | 1 | public function getWebhooksDeliveredAt(): ?\DateTimeImmutable |
|
523 | } |
||
524 |
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..