Completed
Push — master ( abb491...352f9f )
by Olivier
01:38
created

Invoice   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 502
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 98.53%

Importance

Changes 0
Metric Value
wmc 53
lcom 1
cbo 7
dl 0
loc 502
ccs 134
cts 136
cp 0.9853
rs 6.96
c 0
b 0
f 0

43 Methods

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