Passed
Push — develop ( b1e155...c8a590 )
by Reüel
05:09
created

Subscription::save()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

490
		return get_post_meta( /** @scrutinizer ignore-type */ $this->id, $key, true );
Loading history...
491
	}
492
493
	/**
494
	 * Set meta data.
495
	 *
496
	 * @param  string $key   A meta key.
497
	 * @param  mixed  $value A meta value.
498
	 *
499
	 * @return boolean        True on successful update, false on failure.
500
	 */
501
	public function set_meta( $key, $value = false ) {
502
		$key = '_pronamic_subscription_' . $key;
503
504
		if ( $value instanceof DateTime ) {
505
			$value = $value->format( 'Y-m-d H:i:s' );
506
		}
507
508
		if ( empty( $value ) ) {
509
			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

509
			return delete_post_meta( /** @scrutinizer ignore-type */ $this->id, $key );
Loading history...
510
		}
511
512
		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

512
		return update_post_meta( /** @scrutinizer ignore-type */ $this->id, $key, $value );
Loading history...
513
	}
514
515
	/**
516
	 * Get source description.
517
	 *
518
	 * @return string
519
	 */
520
	public function get_source_description() {
521
		$description = $this->source;
522
523
		$payment = $this->get_first_payment();
524
525
		if ( $payment ) {
0 ignored issues
show
introduced by
$payment is of type Pronamic\WordPress\Pay\Subscriptions\Payment, thus it always evaluated to true.
Loading history...
526
			$description = apply_filters( 'pronamic_payment_source_description', $description, $payment );
527
			$description = apply_filters( 'pronamic_payment_source_description_' . $this->source, $description, $payment );
528
		}
529
530
		return $description;
531
	}
532
533
	/**
534
	 * Get source link for this subscription.
535
	 *
536
	 * @return string
537
	 */
538
	public function get_source_link() {
539
		$url = null;
540
541
		$payment = $this->get_first_payment();
542
543
		if ( $payment ) {
0 ignored issues
show
introduced by
$payment is of type Pronamic\WordPress\Pay\Subscriptions\Payment, thus it always evaluated to true.
Loading history...
544
			$url = apply_filters( 'pronamic_payment_source_url', $url, $payment );
545
			$url = apply_filters( 'pronamic_payment_source_url_' . $this->source, $url, $payment );
546
		}
547
548
		return $url;
549
	}
550
551
	/**
552
	 * Get cancel URL for this subscription.
553
	 *
554
	 * @return string
555
	 */
556
	public function get_cancel_url() {
557
		$cancel_url = add_query_arg(
558
			array(
559
				'subscription' => $this->get_id(),
560
				'key'          => $this->get_key(),
561
				'action'       => 'cancel',
562
			), home_url()
563
		);
564
565
		return $cancel_url;
566
	}
567
568
	/**
569
	 * Get renewal URL for this subscription.
570
	 *
571
	 * @return string
572
	 */
573
	public function get_renewal_url() {
574
		$renewal_url = add_query_arg(
575
			array(
576
				'subscription' => $this->get_id(),
577
				'key'          => $this->get_key(),
578
				'action'       => 'renew',
579
			), home_url()
580
		);
581
582
		return $renewal_url;
583
	}
584
585
	/**
586
	 * Get all the payments for this subscription.
587
	 *
588
	 * @return array
589
	 */
590
	public function get_payments() {
591
		return get_pronamic_payments_by_meta( '_pronamic_payment_subscription_id', $this->id );
592
	}
593
594
	/**
595
	 * Get the first payment of this subscription.
596
	 *
597
	 * @return Payment
0 ignored issues
show
Bug introduced by
The type Pronamic\WordPress\Pay\Subscriptions\Payment was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
598
	 */
599
	public function get_first_payment() {
600
		$payments = $this->get_payments();
601
602
		if ( count( $payments ) > 0 ) {
603
			return $payments[0];
604
		}
605
606
		return null;
607
	}
608
609
	/**
610
	 * Get the start date of this subscription.
611
	 *
612
	 * @return DateTime|null
613
	 */
614
	public function get_start_date() {
615
		return $this->start_date;
616
	}
617
618
	/**
619
	 * Set the start date of this subscription.
620
	 *
621
	 * @param DateTime $date Start date.
622
	 */
623
	public function set_start_date( DateTime $date ) {
0 ignored issues
show
Unused Code introduced by
The parameter $date is not used and could be removed. ( Ignorable by Annotation )

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

623
	public function set_start_date( /** @scrutinizer ignore-unused */ DateTime $date ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
624
		$this->start_date = $value;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $value seems to be never defined.
Loading history...
625
	}
626
627
	/**
628
	 * Get the end date of this subscription.
629
	 *
630
	 * @return DateTime|null
631
	 */
632
	public function get_end_date() {
633
		return $this->end_date;
634
	}
635
636
	/**
637
	 * Set the end date of this subscription.
638
	 *
639
	 * @param DateTime|null $date End date.
640
	 */
641
	public function set_end_date( DateTime $date ) {
642
		$this->end_date = $date;
643
	}
644
645
	/**
646
	 * Get the expiry date of this subscription.
647
	 *
648
	 * @return DateTime
649
	 */
650
	public function get_expiry_date() {
651
		return $this->expiry_date;
652
	}
653
654
	/**
655
	 * Set the expiry date of this subscription.
656
	 *
657
	 * @param DateTime $date Expiry date.
658
	 */
659
	public function set_expiry_date( DateTime $date ) {
0 ignored issues
show
Unused Code introduced by
The parameter $date is not used and could be removed. ( Ignorable by Annotation )

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

659
	public function set_expiry_date( /** @scrutinizer ignore-unused */ DateTime $date ) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
660
		$this->expiry_date = $expiry_date;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $expiry_date seems to be never defined.
Loading history...
661
	}
662
663
	/**
664
	 * Set the next payment date of this subscription.
665
	 *
666
	 * @param DateTime $date Next payment date.
667
	 */
668
	public function set_next_payment_date( DateTime $date ) {
669
		$this->next_payment = $date;
670
	}
671
672
	/**
673
	 * Get the next payment date of this subscription.
674
	 *
675
	 * @return DateTime
676
	 */
677
	public function get_next_payment_date() {
678
		return $this->next_payment;
679
	}
680
681
	/**
682
	 * Update meta.
683
	 *
684
	 * @todo  Not sure how and when this function is used.
685
	 * @param array $meta The meta data to update.
686
	 */
687
	public function update_meta( $meta ) {
688
		if ( ! is_array( $meta ) || count( $meta ) === 0 ) {
0 ignored issues
show
introduced by
The condition is_array($meta) is always true.
Loading history...
689
			return;
690
		}
691
692
		$note = sprintf(
693
			'<p>%s:</p>',
694
			__( 'Subscription changed', 'pronamic_ideal' )
695
		);
696
697
		$note .= '<dl>';
698
699
		foreach ( $meta as $key => $value ) {
700
			$this->set_meta( $key, $value );
701
702
			if ( $value instanceof DateTime ) {
703
				$value = date_i18n( __( 'l jS \o\f F Y, h:ia', 'pronamic_ideal' ), $value->getTimestamp() );
704
			}
705
706
			$note .= sprintf( '<dt>%s</dt>', esc_html( $key ) );
707
			$note .= sprintf( '<dd>%s</dd>', esc_html( $value ) );
708
		}
709
710
		$note .= '</dl>';
711
712
		$this->add_note( $note );
713
	}
714
715
	/**
716
	 * Save subscription.
717
	 *
718
	 * @return void
719
	 */
720
	public function save() {
721
		pronamic_pay_plugin()->subscriptions_data_store->update( $this );
722
	}
723
}
724