Completed
Push — master ( 3852cf...e9c0f9 )
by Olivier
02:35
created

Invoice   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 490
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 98.5%

Importance

Changes 0
Metric Value
wmc 52
lcom 1
cbo 7
dl 0
loc 490
ccs 131
cts 133
cp 0.985
rs 7.44
c 0
b 0
f 0

42 Methods

Rating   Name   Duplication   Size   Complexity  
F createFromArray() 0 58 11
A getId() 0 4 1
A getAmountDue() 0 4 1
A getAmountPaid() 0 4 1
A getAmountRemaining() 0 4 1
A getApplicationFeeAmount() 0 4 1
A getAttemptCount() 0 4 1
A isAttempted() 0 4 1
A isAutoAdvance() 0 4 1
A getBilling() 0 4 1
A getBillingReason() 0 4 1
A getCharge() 0 4 1
A getCreatedAt() 0 4 1
A getCurrency() 0 4 1
A getCustomFields() 0 4 1
A getCustomer() 0 4 1
A getDefaultSource() 0 4 1
A getDescription() 0 4 1
A getDiscount() 0 4 1
A getDueAt() 0 4 1
A getEndingBalance() 0 4 1
A getFooter() 0 4 1
A getHostedInvoiceUrl() 0 4 1
A getInvoicePdf() 0 4 1
A getLines() 0 4 1
A getNextPaymentAttempt() 0 4 1
A getNumber() 0 4 1
A isPaid() 0 4 1
A getPeriodEndAt() 0 4 1
A getPeriodStartAt() 0 4 1
A getReceiptNumber() 0 4 1
A getStartingBalance() 0 4 1
A getStatementDescriptor() 0 4 1
A getStatus() 0 4 1
A getSubscription() 0 4 1
A getSubscriptionProrationAt() 0 4 1
A getSubtotal() 0 4 1
A getTax() 0 4 1
A getTaxPercent() 0 4 1
A getThresholdReason() 0 4 1
A getTotal() 0 4 1
A getWebhooksDeliveredAt() 0 4 1

How to fix   Complexity   

Complex Class

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
2
3
declare(strict_types=1);
4
5
/*
6
 * This software may be modified and distributed under the terms
7
 * of the MIT license. See the LICENSE file for details.
8
 */
9
10
namespace Shapin\Stripe\Model\Invoice;
11
12
use Shapin\Stripe\Model\ContainsMetadata;
13
use Shapin\Stripe\Model\CreatableFromArray;
14
use Shapin\Stripe\Model\Customer\CustomField;
15
use Shapin\Stripe\Model\Discount\Discount;
16
use Shapin\Stripe\Model\LivemodeTrait;
17
use Shapin\Stripe\Model\MetadataTrait;
18
use Shapin\Stripe\Model\MetadataCollection;
19
use Money\Currency;
20
use Money\Money;
21
22
final class Invoice implements CreatableFromArray, ContainsMetadata
23
{
24
    use LivemodeTrait, MetadataTrait;
25
26
    const BILLING_CHARGE_AUTOMATICALLY = 'charge_automatically';
27
    const BILLING_SEND_INVOICE = 'send_invoice';
28
29
    const BILLING_REASON_SUBSCRIPTION_CYCLE = 'subscription_cycle';
30
    const BILLING_REASON_SUBSCRIPTION_CREATE = 'subscription_create';
31
    const BILLING_REASON_SUBSCRIPTION_UPDATE = 'subscription_update';
32
    const BILLING_REASON_SUBSCRIPTION = 'subscription';
33
    const BILLING_REASON_MANUAL = 'manual';
34
    const BILLING_REASON_UPCOMING = 'upcoming';
35
    const BILLING_REASON_SUBSCRIPTION_THRESHOLD = 'subscription_threshold';
36
37
    const STATUS_DRAFT = 'draft';
38
    const STATUS_OPEN = 'open';
39
    const STATUS_PAID = 'paid';
40
    const STATUS_UNCOLLECTIBLE = 'uncollectible';
41
    const STATUS_VOID = 'void';
42
43
    /**
44
     * @var ?string
45
     */
46
    private $id;
47
48
    /**
49
     * @var Money
50
     */
51
    private $amountDue;
52
53
    /**
54
     * @var Money
55
     */
56
    private $amountPaid;
57
58
    /**
59
     * @var Money
60
     */
61
    private $amountRemaining;
62
63
    /**
64
     * @var ?Money
65
     */
66
    private $applicationFeeAmount;
67
68
    /**
69
     * @var int
70
     */
71
    private $attemptCount;
72
73
    /**
74
     * @var bool
75
     */
76
    private $attempted;
77
78
    /**
79
     * @var bool
80
     */
81
    private $autoAdvance;
82
83
    /**
84
     * @var string
85
     */
86
    private $billing;
87
88
    /**
89
     * @var string
90
     */
91
    private $billingReason;
92
93
    /**
94
     * @var ?string
95
     */
96
    private $charge;
97
98
    /**
99
     * @var \DateTimeImmutable
100
     */
101
    private $createdAt;
102
103
    /**
104
     * @var Currency
105
     */
106
    private $currency;
107
108
    /**
109
     * @var array
110
     */
111
    private $customFields;
112
113
    /**
114
     * @var string
115
     */
116
    private $customer;
117
118
    /**
119
     * @var ?string
120
     */
121
    private $defaultSource;
122
123
    /**
124
     * @var string
125
     */
126
    private $description;
127
128
    /**
129
     * @var ?Discount
130
     */
131
    private $discount;
132
133
    /**
134
     * @var ?\DateTimeImmutable
135
     */
136
    private $dueAt;
137
138
    /**
139
     * @var ?Money
140
     */
141
    private $endingBalance;
142
143
    /**
144
     * @var ?string
145
     */
146
    private $footer;
147
148
    /**
149
     * @var ?string
150
     */
151
    private $hostedInvoiceUrl;
152
153
    /**
154
     * @var ?string
155
     */
156
    private $invoicePdf;
157
158
    /**
159
     * @var LineItemCollection
160
     */
161
    private $lines;
162
163
    /**
164
     * @var ?\DateTimeImmutable
165
     */
166
    private $nextPaymentAttempt;
167
168
    /**
169
     * @var string
170
     */
171
    private $number;
172
173
    /**
174
     * @var bool
175
     */
176
    private $paid;
177
178
    /**
179
     * @var \DateTimeImmutable
180
     */
181
    private $periodEndAt;
182
183
    /**
184
     * @var \DateTimeImmutable
185
     */
186
    private $periodStartAt;
187
188
    /**
189
     * @var ?string
190
     */
191
    private $receiptNumber;
192
193
    /**
194
     * @var Money
195
     */
196
    private $startingBalance;
197
198
    /**
199
     * @var ?string
200
     */
201
    private $statementDescriptor;
202
203
    /**
204
     * @var string
205
     */
206
    private $status;
207
208
    /**
209
     * @var string
210
     */
211
    private $subscription;
212
213
    /**
214
     * @var ?\DateTimeImmutable
215
     */
216
    private $subscriptionProrationAt;
217
218
    /**
219
     * @var Money
220
     */
221
    private $subtotal;
222
223
    /**
224
     * @var Money
225
     */
226
    private $tax;
227
228
    /**
229
     * @var float
230
     */
231
    private $taxPercent;
232
233
    /**
234
     * @var ?ThresholdReason
235
     */
236
    private $thresholdReason;
237
238
    /**
239
     * @var Money
240
     */
241
    private $total;
242
243
    /**
244
     * @var ?\DateTimeImmutable
245
     */
246
    private $webhooksDeliveredAt;
247
248 12
    public static function createFromArray(array $data): self
249
    {
250 12
        $currency = new Currency(strtoupper($data['currency']));
251
252 12
        $customFields = [];
253 12
        if (isset($data['custom_fields'])) {
254
            foreach ($data['custom_fields'] as $customField) {
255
                $customFields[] = new CustomField($customField['name'], $customField['value']);
256
            }
257
        }
258
259 12
        $model = new self();
260 12
        $model->id = $data['id'];
261 12
        $model->amountDue = new Money($data['amount_due'], $currency);
262 12
        $model->amountPaid = new Money($data['amount_paid'], $currency);
263 12
        $model->amountRemaining = new Money($data['amount_remaining'], $currency);
264 12
        $model->applicationFeeAmount = isset($data['application_fee_amount']) ? new Money($data['application_fee_amount'], $currency) : null;
265 12
        $model->attemptCount = (int) $data['attempt_count'];
266 12
        $model->attempted = (bool) $data['attempted'];
267 12
        $model->autoAdvance = (bool) $data['auto_advance'];
268 12
        $model->billing = $data['billing'];
269 12
        $model->billingReason = $data['billing_reason'];
270 12
        $model->charge = $data['charge'];
271 12
        $model->createdAt = new \DateTimeImmutable('@'.$data['created']);
272 12
        $model->currency = $currency;
273 12
        $model->customFields = $customFields;
274 12
        $model->customer = $data['customer'];
275 12
        $model->defaultSource = $data['default_source'] ?? null;
276 12
        $model->description = $data['description'];
277 12
        $model->discount = isset($data['discount']) ? Discount::createFromArray($data['discount']) : null;
278 12
        $model->dueAt = isset($data['due_at']) ? new \DateTimeImmutable('@'.$data['due_at']) : null;
279 12
        $model->endingBalance = isset($data['ending_balance']) ? new Money($data['ending_balance'], $currency) : null;
280 12
        $model->footer = $data['footer'] ?? null;
281 12
        $model->hostedInvoiceUrl = $data['hosted_invoice_url'];
282 12
        $model->invoicePdf = $data['invoice_pdf'];
283 12
        $model->lines = LineItemCollection::createFromArray($data['lines']);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Shapin\Stripe\Model\Inv...omArray($data['lines']) of type object<self> is incompatible with the declared type object<Shapin\Stripe\Mod...ice\LineItemCollection> of property $lines.

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...
284 12
        $model->live = $data['livemode'];
285 12
        $model->metadata = MetadataCollection::createFromArray($data['metadata']);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Shapin\Stripe\Model\Met...rray($data['metadata']) of type object<self> is incompatible with the declared type object<Shapin\Stripe\Model\MetadataCollection> of property $metadata.

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...
286 12
        $model->nextPaymentAttempt = isset($data['next_payment_attempt']) ? new \DateTimeImmutable('@'.$data['next_payment_attempt']) : null;
287 12
        $model->number = $data['number'];
288 12
        $model->paid = (bool) $data['paid'];
289 12
        $model->periodEndAt = new \DateTimeImmutable('@'.$data['period_end']);
290 12
        $model->periodStartAt = new \DateTimeImmutable('@'.$data['period_start']);
291 12
        $model->receiptNumber = $data['receipt_number'];
292 12
        $model->startingBalance = new Money($data['starting_balance'], $currency);
293 12
        $model->statementDescriptor = $data['statement_descriptor'];
294 12
        $model->status = $data['status'];
295 12
        $model->subscription = $data['subscription'];
296 12
        $model->subscriptionProrationAt = isset($data['subscription_proration_at']) ? new \DateTimeImmutable('@'.$data['subscription_proration_at']) : null;
297 12
        $model->subtotal = new Money($data['subtotal'], $currency);
298 12
        $model->tax = new Money($data['tax'], $currency);
299 12
        $model->taxPercent = (float) $data['tax_percent'];
300 12
        $model->thresholdReason = isset($data['threshold_reason']) ? ThresholdReason::createFromArray($data['threshold_reason']) : null;
301 12
        $model->total = new Money($data['total'], $currency);
302 12
        $model->webhooksDeliveredAt = isset($data['webhooks_delivered_at']) ? new \DateTimeImmutable('@'.$data['webhooks_delivered_at']) : null;
303
304 12
        return $model;
305
    }
306
307 1
    public function getId(): ?string
308
    {
309 1
        return $this->id;
310
    }
311
312 1
    public function getAmountDue(): Money
313
    {
314 1
        return $this->amountDue;
315
    }
316
317 1
    public function getAmountPaid(): Money
318
    {
319 1
        return $this->amountPaid;
320
    }
321
322 1
    public function getAmountRemaining(): Money
323
    {
324 1
        return $this->amountRemaining;
325
    }
326
327 1
    public function getApplicationFeeAmount(): ?Money
328
    {
329 1
        return $this->applicationFeeAmount;
330
    }
331
332 1
    public function getAttemptCount(): int
333
    {
334 1
        return $this->attemptCount;
335
    }
336
337 1
    public function isAttempted(): bool
338
    {
339 1
        return $this->attempted;
340
    }
341
342 1
    public function isAutoAdvance(): bool
343
    {
344 1
        return $this->autoAdvance;
345
    }
346
347 1
    public function getBilling(): string
348
    {
349 1
        return $this->billing;
350
    }
351
352 1
    public function getBillingReason(): string
353
    {
354 1
        return $this->billingReason;
355
    }
356
357 1
    public function getCharge(): ?string
358
    {
359 1
        return $this->charge;
360
    }
361
362 1
    public function getCreatedAt(): \DateTimeImmutable
363
    {
364 1
        return $this->createdAt;
365
    }
366
367 1
    public function getCurrency(): Currency
368
    {
369 1
        return $this->currency;
370
    }
371
372 1
    public function getCustomFields(): array
373
    {
374 1
        return $this->customFields;
375
    }
376
377 1
    public function getCustomer(): string
378
    {
379 1
        return $this->customer;
380
    }
381
382 1
    public function getDefaultSource(): ?string
383
    {
384 1
        return $this->defaultSource;
385
    }
386
387 1
    public function getDescription(): ?string
388
    {
389 1
        return $this->description;
390
    }
391
392 1
    public function getDiscount(): ?Discount
393
    {
394 1
        return $this->discount;
395
    }
396
397 1
    public function getDueAt(): ?\DateTimeImmutable
398
    {
399 1
        return $this->dueAt;
400
    }
401
402 1
    public function getEndingBalance(): ?Money
403
    {
404 1
        return $this->endingBalance;
405
    }
406
407 1
    public function getFooter(): ?string
408
    {
409 1
        return $this->footer;
410
    }
411
412 1
    public function getHostedInvoiceUrl(): ?string
413
    {
414 1
        return $this->hostedInvoiceUrl;
415
    }
416
417 1
    public function getInvoicePdf(): ?string
418
    {
419 1
        return $this->invoicePdf;
420
    }
421
422 1
    public function getLines(): LineItemCollection
423
    {
424 1
        return $this->lines;
425
    }
426
427 1
    public function getNextPaymentAttempt(): ?\DateTimeImmutable
428
    {
429 1
        return $this->nextPaymentAttempt;
430
    }
431
432 1
    public function getNumber(): string
433
    {
434 1
        return $this->number;
435
    }
436
437 1
    public function isPaid(): bool
438
    {
439 1
        return $this->paid;
440
    }
441
442 1
    public function getPeriodEndAt(): \DateTimeImmutable
443
    {
444 1
        return $this->periodEndAt;
445
    }
446
447 1
    public function getPeriodStartAt(): \DateTimeImmutable
448
    {
449 1
        return $this->periodStartAt;
450
    }
451
452 1
    public function getReceiptNumber(): ?string
453
    {
454 1
        return $this->receiptNumber;
455
    }
456
457 1
    public function getStartingBalance(): Money
458
    {
459 1
        return $this->startingBalance;
460
    }
461
462 1
    public function getStatementDescriptor(): ?string
463
    {
464 1
        return $this->statementDescriptor;
465
    }
466
467 1
    public function getStatus(): string
468
    {
469 1
        return $this->status;
470
    }
471
472 1
    public function getSubscription(): ?string
473
    {
474 1
        return $this->subscription;
475
    }
476
477 1
    public function getSubscriptionProrationAt(): ?\DateTimeImmutable
478
    {
479 1
        return $this->subscriptionProrationAt;
480
    }
481
482 1
    public function getSubtotal(): Money
483
    {
484 1
        return $this->subtotal;
485
    }
486
487 1
    public function getTax(): Money
488
    {
489 1
        return $this->tax;
490
    }
491
492 1
    public function getTaxPercent(): float
493
    {
494 1
        return $this->taxPercent;
495
    }
496
497 1
    public function getThresholdReason(): ?ThresholdReason
498
    {
499 1
        return $this->thresholdReason;
500
    }
501
502 1
    public function getTotal(): Money
503
    {
504 1
        return $this->total;
505
    }
506
507 1
    public function getWebhooksDeliveredAt(): ?\DateTimeImmutable
508
    {
509 1
        return $this->webhooksDeliveredAt;
510
    }
511
}
512