Passed
Push — develop ( 0321f9...73d743 )
by Reüel
09:16 queued 04:10
created

Subscription   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 711
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 711
rs 8
c 0
b 0
f 0
wmc 50

40 Methods

Rating   Name   Duplication   Size   Complexity  
A set_end_date() 0 2 1
A get_expiry_date() 0 2 1
A get_interval_period() 0 2 1
A set_meta() 0 12 3
B update_meta() 0 26 5
A get_status() 0 2 1
A get_date_interval() 0 6 1
A save() 0 2 1
A get_meta() 0 4 1
A set_consumer_name() 0 2 1
A get_transaction_id() 0 2 1
A get_amount() 0 2 1
A set_amount() 0 2 1
A get_description() 0 2 1
A get_start_date() 0 2 1
A set_transaction_id() 0 2 1
A get_interval() 0 2 1
A get_next_payment_date() 0 2 1
A get_source() 0 2 1
A get_first_payment() 0 8 2
A get_source_description() 0 11 2
A __construct() 0 9 2
A set_status() 0 2 1
A set_expiry_date() 0 2 1
A get_source_link() 0 11 2
A get_frequency() 0 2 1
A get_payments() 0 2 1
A get_currency() 0 2 1
A get_id() 0 2 1
A set_consumer_iban() 0 2 1
A get_source_id() 0 2 1
A set_next_payment_date() 0 2 1
A get_cancel_url() 0 10 1
A set_consumer_bic() 0 2 1
A get_end_date() 0 2 1
A get_renewal_url() 0 10 1
A set_id() 0 2 1
A add_note() 0 12 1
A set_start_date() 0 2 1
A get_key() 0 2 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
 * Subscription
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2018 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Subscriptions
9
 */
10
11
namespace Pronamic\WordPress\Pay\Subscriptions;
12
13
use DateInterval;
14
use Pronamic\WordPress\DateTime\DateTime;
15
use Pronamic\WordPress\Money\Currency;
16
use Pronamic\WordPress\Money\Money;
17
use Pronamic\WordPress\Pay\Core\Statuses;
18
use Pronamic\WordPress\Pay\Payments\Payment;
19
use WP_Post;
20
21
/**
22
 * Subscription.
23
 */
24
class Subscription {
25
	/**
26
	 * The ID of this subscription.
27
	 *
28
	 * @var string
29
	 */
30
	protected $id;
31
32
	/**
33
	 * The date of this subscription.
34
	 *
35
	 * @var DateTime
36
	 */
37
	public $date;
38
39
	/**
40
	 * The key of this subscription, used in URL's for security.
41
	 *
42
	 * @var string
43
	 */
44
	public $key;
45
46
	/**
47
	 * The frequency of this subscription, for example: `daily`, `weekly`, `monthly` or `annually`.
48
	 *
49
	 * @var string
50
	 */
51
	public $frequency;
52
53
	/**
54
	 * The interval of this subscription, for example: 1, 2, 3, etc.
55
	 *
56
	 * @todo Improve documentation?
57
	 * @var  int
58
	 */
59
	public $interval;
60
61
	/**
62
	 * The interval period of this subscription.
63
	 *
64
	 * @todo Improve documentation?
65
	 * @var  int
66
	 */
67
	public $interval_period;
68
69
	/**
70
	 * The transaction ID of this subscription.
71
	 *
72
	 * @todo Is this required within a transaction?
73
	 * @var string
74
	 */
75
	public $transaction_id;
76
77
	/**
78
	 * The description of this subscription.
79
	 *
80
	 * @todo Is this required within a transaction?
81
	 * @var string
82
	 */
83
	public $description;
84
85
	/**
86
	 * The amount of this subscription, for example 18.95.
87
	 *
88
	 * @var Money
89
	 */
90
	protected $amount;
91
92
	/**
93
	 * The status of this subscription, for example 'Success'.
94
	 *
95
	 * @todo How to reference to a class constant?
96
	 * @see  Statuses
97
	 * @var  string
98
	 */
99
	public $status;
100
101
	/**
102
	 * Identifier for the source which started this subsription.
103
	 * For example: 'woocommerce', 'gravityforms', 'easydigitaldownloads', etc.
104
	 *
105
	 * @var string
106
	 */
107
	public $source;
108
109
	/**
110
	 * Unique ID at the source which started this subscription, for example:
111
	 * - WooCommerce order ID.
112
	 * - Easy Digital Downloads payment ID.
113
	 * - Gravity Forms entry ID.
114
	 *
115
	 * @var string
116
	 */
117
	public $source_id;
118
119
	/**
120
	 * The name of the consumer of this subscription.
121
	 *
122
	 * @todo Is this required and should we add the 'consumer' part?
123
	 * @var  string
124
	 */
125
	public $consumer_name;
126
127
	/**
128
	 * The IBAN of the consumer of this subscription.
129
	 *
130
	 * @todo Is this required and should we add the 'consumer' part?
131
	 * @var  string
132
	 */
133
	public $consumer_iban;
134
135
	/**
136
	 * The BIC of the consumer of this subscription.
137
	 *
138
	 * @todo Is this required and should we add the 'consumer' part?
139
	 * @var  string
140
	 */
141
	public $consumer_bic;
142
143
	/**
144
	 * The order ID of this subscription.
145
	 *
146
	 * @todo Is this required?
147
	 * @var  string
148
	 */
149
	public $order_id;
150
151
	/**
152
	 * The address of the consumer of this subscription.
153
	 *
154
	 * @todo Is this required?
155
	 * @var  string
156
	 */
157
	public $address;
158
159
	/**
160
	 * The city of the consumer of this subscription.
161
	 *
162
	 * @todo Is this required?
163
	 * @var  string
164
	 */
165
	public $city;
166
167
	/**
168
	 * The ZIP of the consumer of this subscription.
169
	 *
170
	 * @todo Is this required?
171
	 * @var  string
172
	 */
173
	public $zip;
174
175
	/**
176
	 * The country of the consumer of this subscription.
177
	 *
178
	 * @todo Is this required?
179
	 * @var  string
180
	 */
181
	public $country;
182
183
	/**
184
	 * The telephone number of the consumer of this subscription.
185
	 *
186
	 * @todo Is this required?
187
	 * @var  string
188
	 */
189
	public $telephone_number;
190
191
	/**
192
	 * The gateway configuration ID to use with this subscription.
193
	 *
194
	 * @todo Should we improve the name of this var?
195
	 * @var  integer
196
	 */
197
	public $config_id;
198
199
	/**
200
	 * The email of the consumer of this subscription.
201
	 *
202
	 * @todo Is this required?
203
	 * @var  string
204
	 */
205
	public $email;
206
207
	/**
208
	 * The customer name of the consumer of this subscription.
209
	 *
210
	 * @todo Is this required?
211
	 * @var  string
212
	 */
213
	public $customer_name;
214
215
	/**
216
	 * The payment method which was used to create this subscription.
217
	 *
218
	 * @var  string
219
	 */
220
	public $payment_method;
221
222
	/**
223
	 * The date when this subscirption started.
224
	 *
225
	 * @var DateTime|null
226
	 */
227
	public $start_date;
228
229
	/**
230
	 * The date when this subscirption will end, can be `null`.
231
	 *
232
	 * @var DateTime|null
233
	 */
234
	public $end_date;
235
236
	/**
237
	 * The end date of the last succesfull payment.
238
	 *
239
	 * @var DateTime|null
240
	 */
241
	public $expiry_date;
242
243
	/**
244
	 * The next payment date.
245
	 *
246
	 * @var DateTime|null
247
	 */
248
	public $next_payment;
249
250
	/**
251
	 * Array for extra meta data to store with this subscription.
252
	 *
253
	 * @var array
254
	 */
255
	public $meta;
256
257
	/**
258
	 * WordPress post object related to this subscription.
259
	 *
260
	 * @var WP_Post|array
261
	 */
262
	public $post;
263
264
	/**
265
	 * Construct and initialize subscription object.
266
	 *
267
	 * @param int $post_id A subscription post ID or null.
268
	 */
269
	public function __construct( $post_id = null ) {
270
		$this->id   = $post_id;
271
		$this->date = new DateTime();
272
		$this->meta = array();
273
274
		$this->set_amount( new Money() );
275
276
		if ( null !== $post_id ) {
277
			pronamic_pay_plugin()->subscriptions_data_store->read( $this );
278
		}
279
	}
280
281
	/**
282
	 * Get the ID of this subscription.
283
	 *
284
	 * @return string
285
	 */
286
	public function get_id() {
287
		return $this->id;
288
	}
289
290
	/**
291
	 * Set the ID of this subscription.
292
	 *
293
	 * @param string $id The ID of this subscription.
294
	 */
295
	public function set_id( $id ) {
296
		$this->id = $id;
297
	}
298
299
	/**
300
	 * Get the unique key of this subscription.
301
	 *
302
	 * @return string
303
	 */
304
	public function get_key() {
305
		return $this->key;
306
	}
307
308
	/**
309
	 * Get the source identifier of this subscription, for example: 'woocommerce', 'gravityforms', etc.
310
	 *
311
	 * @return string
312
	 */
313
	public function get_source() {
314
		return $this->source;
315
	}
316
317
	/**
318
	 * Get the source ID of this subscription, for example a WooCommerce order ID or a Gravity Forms entry ID.
319
	 *
320
	 * @return string
321
	 */
322
	public function get_source_id() {
323
		return $this->source_id;
324
	}
325
326
	/**
327
	 * Get the frequency of this subscription, for example: 'daily', 'weekly', 'monthly' or 'annually'.
328
	 *
329
	 * @return string
330
	 */
331
	public function get_frequency() {
332
		return $this->frequency;
333
	}
334
335
	/**
336
	 * Get the interval, for example: 1, 2, 3, 4, etc., this specifies for example:
337
	 * - Repeat every *2* days
338
	 * - Repeat every *1* months
339
	 * - Repeat every *2* year
340
	 *
341
	 * @return int
342
	 */
343
	public function get_interval() {
344
		return $this->interval;
345
	}
346
347
	/**
348
	 * Get the interval period, for example 'D', 'M', 'Y', etc.
349
	 *
350
	 * @see    http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
351
	 * @return string
352
	 */
353
	public function get_interval_period() {
354
		return $this->interval_period;
355
	}
356
357
	/**
358
	 * Get date interval.
359
	 *
360
	 * @see http://php.net/manual/en/dateinterval.construct.php#refsect1-dateinterval.construct-parameters
361
	 * @return \DateInterval
362
	 * @throws \Exception    Throws an Exception when the `interval_spec` cannot be parsed as an interval.
363
	 */
364
	public function get_date_interval() {
365
		$interval_spec = 'P' . $this->interval . $this->interval_period;
366
367
		$interval = new DateInterval( $interval_spec );
368
369
		return $interval;
370
	}
371
372
	/**
373
	 * Get the description of this subscription.
374
	 *
375
	 * @return string
376
	 */
377
	public function get_description() {
378
		return $this->description;
379
	}
380
381
	/**
382
	 * Get the currency of this subscription.
383
	 *
384
	 * @return Currency
385
	 */
386
	public function get_currency() {
387
		return $this->get_amount()->get_currency()->get_alphabetic_code();
388
	}
389
390
	/**
391
	 * Get the amount of this subscription.
392
	 *
393
	 * @return Money
394
	 */
395
	public function get_amount() {
396
		return $this->amount;
397
	}
398
399
	/**
400
	 * Set the amount of this subscription.
401
	 *
402
	 * @param Money $amount Money object.
403
	 *
404
	 * @return void
405
	 */
406
	public function set_amount( Money $amount ) {
407
		$this->amount = $amount;
408
	}
409
410
	/**
411
	 * Get the transaction ID of this subscription.
412
	 *
413
	 * @return string
414
	 */
415
	public function get_transaction_id() {
416
		return $this->transaction_id;
417
	}
418
419
	/**
420
	 * Set the transaction ID of this subscription.
421
	 *
422
	 * @param string $transaction_id A transaction ID.
423
	 */
424
	public function set_transaction_id( $transaction_id ) {
425
		$this->transaction_id = $transaction_id;
426
	}
427
428
	/**
429
	 * Get the status of this subscription.
430
	 *
431
	 * @todo   Check constant?
432
	 * @return string
433
	 */
434
	public function get_status() {
435
		return $this->status;
436
	}
437
438
	/**
439
	 * Set the status of this subscription.
440
	 *
441
	 * @todo  Check constant?
442
	 * @param string $status A status string.
443
	 */
444
	public function set_status( $status ) {
445
		$this->status = $status;
446
	}
447
448
	/**
449
	 * Set consumer name.
450
	 *
451
	 * @param string $name A name.
452
	 */
453
	public function set_consumer_name( $name ) {
454
		$this->consumer_name = $name;
455
	}
456
457
	/**
458
	 * Set consumer IBAN.
459
	 *
460
	 * @param string $iban A IBAN.
461
	 */
462
	public function set_consumer_iban( $iban ) {
463
		$this->consumer_iban = $iban;
464
	}
465
466
	/**
467
	 * Set consumer BIC.
468
	 *
469
	 * @param string $bic A BIC.
470
	 */
471
	public function set_consumer_bic( $bic ) {
472
		$this->consumer_bic = $bic;
473
	}
474
475
	/**
476
	 * Add the specified note to this subscription.
477
	 *
478
	 * @param string $note A Note.
479
	 */
480
	public function add_note( $note ) {
481
		$commentdata = array(
482
			'comment_post_ID'  => $this->id,
483
			'comment_content'  => $note,
484
			'comment_type'     => 'subscription_note',
485
			'user_id'          => get_current_user_id(),
486
			'comment_approved' => true,
487
		);
488
489
		$comment_id = wp_insert_comment( $commentdata );
490
491
		return $comment_id;
492
	}
493
494
	/**
495
	 * Get meta by the specified meta key.
496
	 *
497
	 * @param string $key A meta key.
498
	 * @return string
499
	 */
500
	public function get_meta( $key ) {
501
		$key = '_pronamic_subscription_' . $key;
502
503
		return get_post_meta( $this->id, $key, true );
0 ignored issues
show
Bug introduced by
$this->id of type string is incompatible with the type integer expected by parameter $post_id of get_post_meta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

503
		return get_post_meta( /** @scrutinizer ignore-type */ $this->id, $key, true );
Loading history...
504
	}
505
506
	/**
507
	 * Set meta data.
508
	 *
509
	 * @param  string $key   A meta key.
510
	 * @param  mixed  $value A meta value.
511
	 *
512
	 * @return boolean        True on successful update, false on failure.
513
	 */
514
	public function set_meta( $key, $value = false ) {
515
		$key = '_pronamic_subscription_' . $key;
516
517
		if ( $value instanceof DateTime ) {
518
			$value = $value->format( 'Y-m-d H:i:s' );
519
		}
520
521
		if ( empty( $value ) ) {
522
			return delete_post_meta( $this->id, $key );
0 ignored issues
show
Bug introduced by
$this->id of type string is incompatible with the type integer expected by parameter $post_id of delete_post_meta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

522
			return delete_post_meta( /** @scrutinizer ignore-type */ $this->id, $key );
Loading history...
523
		}
524
525
		return update_post_meta( $this->id, $key, $value );
0 ignored issues
show
Bug introduced by
$this->id of type string is incompatible with the type integer expected by parameter $post_id of update_post_meta(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

525
		return update_post_meta( /** @scrutinizer ignore-type */ $this->id, $key, $value );
Loading history...
526
	}
527
528
	/**
529
	 * Get source description.
530
	 *
531
	 * @return string
532
	 */
533
	public function get_source_description() {
534
		$description = $this->source;
535
536
		$payment = $this->get_first_payment();
537
538
		if ( $payment ) {
0 ignored issues
show
introduced by
$payment is of type Pronamic\WordPress\Pay\Payments\Payment, thus it always evaluated to true.
Loading history...
539
			$description = apply_filters( 'pronamic_payment_source_description', $description, $payment );
540
			$description = apply_filters( 'pronamic_payment_source_description_' . $this->source, $description, $payment );
541
		}
542
543
		return $description;
544
	}
545
546
	/**
547
	 * Get source link for this subscription.
548
	 *
549
	 * @return string|null
550
	 */
551
	public function get_source_link() {
552
		$url = null;
553
554
		$payment = $this->get_first_payment();
555
556
		if ( $payment ) {
0 ignored issues
show
introduced by
$payment is of type Pronamic\WordPress\Pay\Payments\Payment, thus it always evaluated to true.
Loading history...
557
			$url = apply_filters( 'pronamic_payment_source_url', $url, $payment );
558
			$url = apply_filters( 'pronamic_payment_source_url_' . $this->source, $url, $payment );
559
		}
560
561
		return $url;
562
	}
563
564
	/**
565
	 * Get cancel URL for this subscription.
566
	 *
567
	 * @return string
568
	 */
569
	public function get_cancel_url() {
570
		$cancel_url = add_query_arg(
571
			array(
572
				'subscription' => $this->get_id(),
573
				'key'          => $this->get_key(),
574
				'action'       => 'cancel',
575
			), home_url()
576
		);
577
578
		return $cancel_url;
579
	}
580
581
	/**
582
	 * Get renewal URL for this subscription.
583
	 *
584
	 * @return string
585
	 */
586
	public function get_renewal_url() {
587
		$renewal_url = add_query_arg(
588
			array(
589
				'subscription' => $this->get_id(),
590
				'key'          => $this->get_key(),
591
				'action'       => 'renew',
592
			), home_url()
593
		);
594
595
		return $renewal_url;
596
	}
597
598
	/**
599
	 * Get all the payments for this subscription.
600
	 *
601
	 * @return array
602
	 */
603
	public function get_payments() {
604
		return get_pronamic_payments_by_meta( '_pronamic_payment_subscription_id', $this->id );
605
	}
606
607
	/**
608
	 * Get the first payment of this subscription.
609
	 *
610
	 * @return Payment
611
	 */
612
	public function get_first_payment() {
613
		$payments = $this->get_payments();
614
615
		if ( count( $payments ) > 0 ) {
616
			return $payments[0];
617
		}
618
619
		return null;
620
	}
621
622
	/**
623
	 * Get the start date of this subscription.
624
	 *
625
	 * @return DateTime|null
626
	 */
627
	public function get_start_date() {
628
		return $this->start_date;
629
	}
630
631
	/**
632
	 * Set the start date of this subscription.
633
	 *
634
	 * @param DateTime $date Start date.
635
	 */
636
	public function set_start_date( DateTime $date ) {
637
		$this->start_date = $date;
638
	}
639
640
	/**
641
	 * Get the end date of this subscription.
642
	 *
643
	 * @return DateTime|null
644
	 */
645
	public function get_end_date() {
646
		return $this->end_date;
647
	}
648
649
	/**
650
	 * Set the end date of this subscription.
651
	 *
652
	 * @param DateTime|null $date End date.
653
	 */
654
	public function set_end_date( DateTime $date ) {
655
		$this->end_date = $date;
656
	}
657
658
	/**
659
	 * Get the expiry date of this subscription.
660
	 *
661
	 * @return DateTime
662
	 */
663
	public function get_expiry_date() {
664
		return $this->expiry_date;
665
	}
666
667
	/**
668
	 * Set the expiry date of this subscription.
669
	 *
670
	 * @param DateTime $date Expiry date.
671
	 */
672
	public function set_expiry_date( DateTime $date ) {
673
		$this->expiry_date = $date;
674
	}
675
676
	/**
677
	 * Set the next payment date of this subscription.
678
	 *
679
	 * @param DateTime $date Next payment date.
680
	 */
681
	public function set_next_payment_date( DateTime $date ) {
682
		$this->next_payment = $date;
683
	}
684
685
	/**
686
	 * Get the next payment date of this subscription.
687
	 *
688
	 * @return DateTime
689
	 */
690
	public function get_next_payment_date() {
691
		return $this->next_payment;
692
	}
693
694
	/**
695
	 * Update meta.
696
	 *
697
	 * @todo  Not sure how and when this function is used.
698
	 * @param array $meta The meta data to update.
699
	 */
700
	public function update_meta( $meta ) {
701
		if ( ! is_array( $meta ) || count( $meta ) === 0 ) {
0 ignored issues
show
introduced by
The condition is_array($meta) is always true.
Loading history...
702
			return;
703
		}
704
705
		$note = sprintf(
706
			'<p>%s:</p>',
707
			__( 'Subscription changed', 'pronamic_ideal' )
708
		);
709
710
		$note .= '<dl>';
711
712
		foreach ( $meta as $key => $value ) {
713
			$this->set_meta( $key, $value );
714
715
			if ( $value instanceof DateTime ) {
716
				$value = date_i18n( __( 'l jS \o\f F Y, h:ia', 'pronamic_ideal' ), $value->getTimestamp() );
717
			}
718
719
			$note .= sprintf( '<dt>%s</dt>', esc_html( $key ) );
720
			$note .= sprintf( '<dd>%s</dd>', esc_html( $value ) );
721
		}
722
723
		$note .= '</dl>';
724
725
		$this->add_note( $note );
726
	}
727
728
	/**
729
	 * Save subscription.
730
	 *
731
	 * @return void
732
	 */
733
	public function save() {
734
		pronamic_pay_plugin()->subscriptions_data_store->update( $this );
735
	}
736
}
737