Passed
Branch master (50908e)
by Stiofan
07:01
created

WPInv_Subscription::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 17
rs 10
1
<?php
2
3
// Exit if accessed directly
4
if ( ! defined( 'ABSPATH' ) ) {
5
	exit;
6
}
7
8
9
/**
10
 * The Subscription Class
11
 *
12
 * @since  1.0.0
13
 */
14
class WPInv_Subscription {
15
16
	private $subs_db;
17
18
	public $id                = 0;
19
	public $customer_id       = 0;
20
	public $period            = '';
21
	public $initial_amount    = '';
22
	public $recurring_amount  = '';
23
	public $bill_times        = 0;
24
	public $transaction_id    = '';
25
	public $parent_payment_id = 0;
26
	public $product_id        = 0;
27
	public $created           = '0000-00-00 00:00:00';
28
	public $expiration        = '0000-00-00 00:00:00';
29
	public $trial_period      = '';
30
	public $status            = 'pending';
31
	public $profile_id        = '';
32
	public $gateway           = '';
33
	public $customer;
34
35
	/**
36
	 * Get us started
37
	 *
38
	 * @since  1.0.0
39
	 * @return void
40
	 */
41
	function __construct( $_id_or_object = 0, $_by_profile_id = false ) {
42
43
		$this->subs_db = new WPInv_Subscriptions_DB;
44
45
		if( $_by_profile_id ) {
46
47
			$_sub = $this->subs_db->get_by( 'profile_id', $_id_or_object );
48
49
			if( empty( $_sub ) ) {
50
				return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
51
			}
52
53
			$_id_or_object = $_sub;
54
55
		}
56
57
		return $this->setup_subscription( $_id_or_object );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setup_subscription($_id_or_object) targeting WPInv_Subscription::setup_subscription() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
58
	}
59
60
	/**
61
	 * Setup the subscription object
62
	 *
63
	 * @since  1.0.0
64
	 * @return void
65
	 */
66
	private function setup_subscription( $id_or_object = 0 ) {
67
68
		if( empty( $id_or_object ) ) {
69
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
70
		}
71
72
		if( is_numeric( $id_or_object ) ) {
73
74
			$sub = $this->subs_db->get( $id_or_object );
75
76
		} elseif( is_object( $id_or_object ) ) {
77
78
			$sub = $id_or_object;
79
80
		}
81
82
		if( empty( $sub ) ) {
83
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
84
		}
85
86
		foreach( $sub as $key => $value ) {
87
			$this->$key = $value;
88
		}
89
90
		$this->customer = get_userdata( $this->customer_id );
91
		$this->gateway  = wpinv_get_payment_gateway( $this->parent_payment_id );
92
93
		do_action( 'wpinv_recurring_setup_subscription', $this );
94
95
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type WPInv_Subscription which is incompatible with the documented return type void.
Loading history...
96
	}
97
98
	/**
99
	 * Magic __get function to dispatch a call to retrieve a private property
100
	 *
101
	 * @since 1.0.0
102
	 */
103
	public function __get( $key ) {
104
105
		if( method_exists( $this, 'get_' . $key ) ) {
106
107
			return call_user_func( array( $this, 'get_' . $key ) );
108
109
		} else {
110
111
			return new WP_Error( 'wpinv-subscription-invalid-property', sprintf( __( 'Can\'t get property %s', 'invoicing' ), $key ) );
112
113
		}
114
115
	}
116
117
	/**
118
	 * Creates a subscription
119
	 *
120
	 * @since  1.0.0
121
	 * @param  array  $data Array of attributes for a subscription
122
	 * @return mixed  false if data isn't passed and class not instantiated for creation
123
	 */
124
	public function create( $data = array() ) {
125
126
		if ( $this->id != 0 ) {
127
			return false;
128
		}
129
130
		$defaults = array(
131
			'customer_id'       => 0,
132
			'frequency'         => '',
133
			'period'            => '',
134
			'initial_amount'    => '',
135
			'recurring_amount'  => '',
136
			'bill_times'        => 0,
137
			'parent_payment_id' => 0,
138
			'product_id'        => 0,
139
			'created'           => '',
140
			'expiration'        => '',
141
			'status'            => '',
142
			'profile_id'        => '',
143
		);
144
145
		$args = wp_parse_args( $data, $defaults );
146
147
		if( $args['expiration'] && strtotime( 'NOW', current_time( 'timestamp' ) ) > strtotime( $args['expiration'], current_time( 'timestamp' ) ) ) {
148
149
			if( 'active' == $args['status'] || 'trialling' == $args['status'] ) {
150
151
				// Force an active subscription to expired if expiration date is in the past
152
				$args['status'] = 'expired';
153
154
			}
155
		}
156
157
		do_action( 'wpinv_subscription_pre_create', $args );
158
159
		$id = $this->subs_db->insert( $args, 'subscription' );
160
161
		do_action( 'wpinv_subscription_post_create', $id, $args );
162
163
		return $this->setup_subscription( $id );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setup_subscription($id) targeting WPInv_Subscription::setup_subscription() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
164
165
	}
166
167
	/**
168
	 * Updates a subscription
169
	 *
170
	 * @since  1.0.0
171
	 * @param  array $args Array of fields to update
172
	 * @return bool
173
	 */
174
	public function update( $args = array() ) {
175
176
		$ret = $this->subs_db->update( $this->id, $args );
177
178
		do_action( 'wpinv_recurring_update_subscription', $this->id, $args, $this );
179
180
		return $ret;
181
182
	}
183
184
	/**
185
	 * Delete the subscription
186
	 *
187
	 * @since  1.0.0
188
	 * @return bool
189
	 */
190
	public function delete() {
191
		return $this->subs_db->delete( $this->id );
192
	}
193
194
    /**
195
     * Retrieves the parent payment ID
196
     *
197
     * @since  1.0.0
198
     * @return int
199
     */
200
    public function get_original_payment_id() {
201
        return $this->parent_payment_id;
202
    }
203
204
    /**
205
     * Retrieve renewal payments for a subscription
206
     *
207
     * @since  1.0.0
208
     * @return array
209
     */
210
    public function get_child_payments() {
211
        $payments = get_posts( array(
212
            'post_parent'    => (int) $this->parent_payment_id,
213
            'posts_per_page' => '999',
214
            'post_status'    => array( 'publish', 'wpi-processing', 'wpi-renewal' ),
215
            'orderby'           => 'ID',
216
            'order'             => 'DESC',
217
            'post_type'      => 'wpi_invoice'
218
        ) );
219
220
        return $payments;
221
    }
222
223
    /**
224
     * Counts the number of payments made to the subscription
225
     *
226
     * @since  2.4
227
     * @return int
228
     */
229
    public function get_total_payments() {
230
        $child_payments = $this->get_child_payments();
231
        $total_payments = !empty( $child_payments ) ? count( $child_payments ) : 0;
232
233
        if ( 'pending' != $this->status ) {
234
                $total_payments++;
235
        }
236
237
        return $total_payments;
238
    }
239
240
    /**
241
     * Returns the number of times the subscription has been billed
242
     *
243
     * @since  1.0.2
244
     * @return int
245
     */
246
    public function get_times_billed() {
247
        $times_billed = (int)$this->get_total_payments();
248
249
        if ( ! empty( $this->trial_period ) && $times_billed > 0 ) {
250
            $times_billed--;
251
        }
252
253
        return $times_billed;
254
    }
255
256
    /**
257
     * Records a new payment on the subscription
258
     *
259
     * @since  2.4
260
     * @param  array $args Array of values for the payment, including amount and transaction ID
261
     * @return bool
262
     */
263
    public function add_payment( $args = array() ) {
264
        if ( ! $this->parent_payment_id ) {
265
            return false;
266
        }
267
268
        $args = wp_parse_args( $args, array(
269
            'amount'         => '',
270
            'transaction_id' => '',
271
            'gateway'        => ''
272
        ) );
273
        
274
        if ( empty( $args['transaction_id'] ) || $this->payment_exists( $args['transaction_id'] ) ) {
275
            return false;
276
        }
277
        
278
        $parent_invoice = wpinv_get_invoice( $this->parent_payment_id );
279
        if ( empty( $parent_invoice->ID ) ) {
280
            return false;
281
        }
282
283
        $invoice = new WPInv_Invoice();
284
        $invoice->set( 'post_type', 'wpi_invoice' );
285
        $invoice->set( 'parent_invoice', $this->parent_payment_id );
286
        $invoice->set( 'currency', $parent_invoice->get_currency() );
287
        $invoice->set( 'transaction_id', $args['transaction_id'] );
288
        $invoice->set( 'key', $parent_invoice->generate_key() );
289
        $invoice->set( 'ip', $parent_invoice->ip );
290
        $invoice->set( 'user_id', $parent_invoice->get_user_id() );
291
        $invoice->set( 'first_name', $parent_invoice->get_first_name() );
292
        $invoice->set( 'last_name', $parent_invoice->get_last_name() );
293
        $invoice->set( 'phone', $parent_invoice->phone );
294
        $invoice->set( 'address', $parent_invoice->address );
295
        $invoice->set( 'city', $parent_invoice->city );
296
        $invoice->set( 'country', $parent_invoice->country );
297
        $invoice->set( 'state', $parent_invoice->state );
298
        $invoice->set( 'zip', $parent_invoice->zip );
299
        $invoice->set( 'company', $parent_invoice->company );
300
        $invoice->set( 'vat_number', $parent_invoice->vat_number );
301
        $invoice->set( 'vat_rate', $parent_invoice->vat_rate );
302
        $invoice->set( 'adddress_confirmed', $parent_invoice->adddress_confirmed );
303
304
        if ( empty( $args['gateway'] ) ) {
305
            $invoice->set( 'gateway', $parent_invoice->get_gateway() );
306
        } else {
307
            $invoice->set( 'gateway', $args['gateway'] );
308
        }
309
        
310
        $recurring_details = $parent_invoice->get_recurring_details();
311
312
        // increase the earnings for each item in the subscription
313
        $items = $recurring_details['cart_details'];
314
        
315
        if ( $items ) {        
316
            $add_items      = array();
317
            $cart_details   = array();
318
            
319
            foreach ( $items as $item ) {
320
                $add_item             = array();
321
                $add_item['id']       = $item['id'];
322
                $add_item['quantity'] = $item['quantity'];
323
                
324
                $add_items[]    = $add_item;
325
                $cart_details[] = $item;
326
                break;
327
            }
328
            
329
            $invoice->set( 'items', $add_items );
330
            $invoice->cart_details = $cart_details;
331
        }
332
        
333
        $total = $args['amount'];
334
        
335
        $subtotal           = $recurring_details['subtotal'];
336
        $tax                = $recurring_details['tax'];
337
        $discount           = $recurring_details['discount'];
338
        
339
        if ( $discount > 0 ) {
340
            $invoice->set( 'discount_code', $parent_invoice->discount_code );
341
        }
342
        
343
        $invoice->subtotal = wpinv_round_amount( $subtotal );
344
        $invoice->tax      = wpinv_round_amount( $tax );
345
        $invoice->discount = wpinv_round_amount( $discount );
346
        $invoice->total    = wpinv_round_amount( $total );
347
348
        $invoice  = apply_filters( 'wpinv_subscription_add_payment_save', $invoice, $this, $args );
349
350
        $invoice->save();
351
        $invoice->update_meta( '_wpinv_subscription_id', $this->id );
352
        
353
        if ( !empty( $invoice->ID ) ) {
354
            wpinv_update_payment_status( $invoice->ID, 'publish' );
355
            sleep(1);
356
            wpinv_update_payment_status( $invoice->ID, 'wpi-renewal' );
357
            
358
            $invoice = wpinv_get_invoice( $invoice->ID );
359
360
            do_action( 'wpinv_recurring_add_subscription_payment', $invoice, $this );
361
            do_action( 'wpinv_recurring_record_payment', $invoice->ID, $this->parent_payment_id, $args['amount'], $args['transaction_id'] );
362
            
363
            return $invoice->ID;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $invoice->ID returns the type integer which is incompatible with the documented return type boolean.
Loading history...
364
        }
365
366
        return false;
367
    }
368
369
	/**
370
	 * Retrieves the transaction ID from the subscription
371
	 *
372
	 * @since  1.0.0
373
	 * @return bool
374
	 */
375
	public function get_transaction_id() {
376
377
		if( empty( $this->transaction_id ) ) {
378
379
			$txn_id = wpinv_get_payment_transaction_id( $this->parent_payment_id );
380
381
			if( ! empty( $txn_id ) && (int) $this->parent_payment_id !== (int) $txn_id ) {
382
				$this->set_transaction_id( $txn_id );
383
			}
384
385
		}
386
387
		return $this->transaction_id;
388
389
	}
390
391
	/**
392
	 * Stores the transaction ID for the subscription purchase
393
	 *
394
	 * @since  1.0.0.4
395
	 * @return bool
396
	 */
397
	public function set_transaction_id( $txn_id = '' ) {
398
		$this->update( array( 'transaction_id' => $txn_id ) );
399
		$this->transaction_id = $txn_id;
400
	}
401
402
	/**
403
	 * Renews a subscription
404
	 *
405
	 * @since  1.0.0
406
	 * @return bool
407
	 */
408
	public function renew() {
409
410
		$expires = $this->get_expiration_time();
411
412
413
		// Determine what date to use as the start for the new expiration calculation
414
		if( $expires > current_time( 'timestamp' ) && $this->is_active() ) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->is_active() targeting WPInv_Subscription::is_active() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
415
416
			$base_date  = $expires;
417
418
		} else {
419
420
			$base_date  = current_time( 'timestamp' );
421
422
		}
423
424
		$last_day = wpinv_cal_days_in_month( CAL_GREGORIAN, date( 'n', $base_date ), date( 'Y', $base_date ) );
425
426
427
		$frequency = isset($this->frequency) ? $this->frequency : 1;
0 ignored issues
show
Bug Best Practice introduced by
The property frequency does not exist on WPInv_Subscription. Since you implemented __get, consider adding a @property annotation.
Loading history...
428
		$expiration = date( 'Y-m-d H:i:s', strtotime( '+' . $frequency . ' ' . $this->period  . ' 23:59:59', $base_date ) );
0 ignored issues
show
Bug introduced by
Are you sure $frequency of type WP_Error|integer|mixed can be used in concatenation? ( Ignorable by Annotation )

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

428
		$expiration = date( 'Y-m-d H:i:s', strtotime( '+' . /** @scrutinizer ignore-type */ $frequency . ' ' . $this->period  . ' 23:59:59', $base_date ) );
Loading history...
429
430
		if( date( 'j', $base_date ) == $last_day && 'day' != $this->period ) {
431
			$expiration = date( 'Y-m-d H:i:s', strtotime( $expiration . ' +2 days' ) );
432
		}
433
434
		$expiration  = apply_filters( 'wpinv_subscription_renewal_expiration', $expiration, $this->id, $this );
435
436
		do_action( 'wpinv_subscription_pre_renew', $this->id, $expiration, $this );
437
438
		$this->status = 'active';
439
		$times_billed = $this->get_times_billed();
440
441
		// Complete subscription if applicable
442
		if ( $this->bill_times > 0 && $times_billed >= $this->bill_times ) {
443
			$this->complete();
444
			$this->status = 'completed';
445
		}
446
447
		$args = array(
448
			'expiration' => $expiration,
449
			'status'     => $this->status,
450
		);
451
452
        $this->subs_db->update( $this->id, $args );
453
454
		do_action( 'wpinv_subscription_post_renew', $this->id, $expiration, $this );
455
		do_action( 'wpinv_recurring_set_subscription_status', $this->id, $this->status, $this );
456
457
	}
458
459
	/**
460
	 * Marks a subscription as completed
461
	 *
462
	 * Subscription is completed when the number of payments matches the billing_times field
463
	 *
464
	 * @since  1.0.0
465
	 * @return void
466
	 */
467
	public function complete() {
468
469
		// Only mark a subscription as complete if it's not already cancelled.
470
		if ( 'cancelled' === $this->status ) {
471
			return;
472
		}
473
474
		$args = array(
475
			'status' => 'completed'
476
		);
477
478
		if( $this->subs_db->update( $this->id, $args ) ) {
479
480
			$this->status = 'completed';
481
482
			do_action( 'wpinv_subscription_completed', $this->id, $this );
483
484
		}
485
486
	}
487
488
	/**
489
	 * Marks a subscription as expired
490
	 *
491
	 * Subscription is completed when the billing times is reached
492
	 *
493
	 * @since  1.0.0
494
	 * @param  $check_expiration bool True if expiration date should be checked with merchant processor before expiring
495
	 * @return void
496
	 */
497
	public function expire( $check_expiration = false ) {
498
499
		$expiration = $this->expiration;
500
501
		if( $check_expiration ) {
502
503
			// check_expiration() updates $this->expiration so compare to $expiration above
504
505
			if( $expiration < $this->get_expiration() && current_time( 'timestamp' ) < $this->get_expiration_time() ) {
506
507
				return false; // Do not mark as expired since real expiration date is in the future
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type void.
Loading history...
508
			}
509
510
		}
511
512
		$args = array(
513
			'status' => 'expired'
514
		);
515
516
		if( $this->subs_db->update( $this->id, $args ) ) {
517
518
			$this->status = 'expired';
519
520
			do_action( 'wpinv_subscription_expired', $this->id, $this );
521
522
		}
523
524
	}
525
526
	/**
527
	 * Marks a subscription as failing
528
	 *
529
	 * @since  2.4.2
530
	 * @return void
531
	 */
532
	public function failing() {
533
534
		$args = array(
535
			'status' => 'failing'
536
		);
537
538
		if( $this->subs_db->update( $this->id, $args ) ) {
539
540
			$this->status = 'failing';
541
542
			do_action( 'wpinv_subscription_failing', $this->id, $this );
543
544
545
		}
546
547
	}
548
549
    /**
550
     * Marks a subscription as cancelled
551
     *
552
     * @since  1.0.0
553
     * @return void
554
     */
555
    public function cancel() {
556
        if ( 'cancelled' === $this->status ) {
557
            return; // Already cancelled
558
        }
559
560
        $args = array(
561
            'status' => 'cancelled'
562
        );
563
564
        if ( $this->subs_db->update( $this->id, $args ) ) {
565
            if ( is_user_logged_in() ) {
566
                $userdata = get_userdata( get_current_user_id() );
567
                $user     = $userdata->display_name;
568
            } else {
569
                $user = __( 'gateway', 'invoicing' );
570
            }
571
572
            $note = sprintf( __( 'Subscription has been cancelled by %s', 'invoicing' ), $user );
573
            wpinv_insert_payment_note( $this->parent_payment_id, $note, '', '', true );
574
575
            $this->status = 'cancelled';
576
577
            do_action( 'wpinv_subscription_cancelled', $this->id, $this );
578
        }
579
    }
580
581
	/**
582
	 * Determines if subscription can be cancelled
583
	 *
584
	 * This method is filtered by payment gateways in order to return true on subscriptions
585
	 * that can be cancelled with a profile ID through the merchant processor
586
	 *
587
	 * @since  1.0.0
588
	 * @return bool
589
	 */
590
	public function can_cancel() {
591
        $ret = false;
592
	    if( $this->gateway === 'manual' || in_array( $this->status, $this->get_cancellable_statuses() ) ) {
593
            $ret = true;
594
        }
595
		return apply_filters( 'wpinv_subscription_can_cancel', $ret, $this );
596
	}
597
598
    /**
599
     * Returns an array of subscription statuses that can be cancelled
600
     *
601
     * @access      public
602
     * @since       1.0.0
603
     * @return      array
604
     */
605
    public function get_cancellable_statuses() {
606
        return apply_filters( 'wpinv_recurring_cancellable_statuses', array( 'active', 'trialling', 'failing' ) );
607
    }
608
609
	/**
610
	 * Retrieves the URL to cancel subscription
611
	 *
612
	 * @since  1.0.0
613
	 * @return string
614
	 */
615
	public function get_cancel_url() {
616
617
		$url = wp_nonce_url( add_query_arg( array( 'wpinv_action' => 'cancel_subscription', 'sub_id' => $this->id ) ), 'wpinv-recurring-cancel' );
618
619
		return apply_filters( 'wpinv_subscription_cancel_url', $url, $this );
620
	}
621
622
	/**
623
	 * Determines if subscription can be manually renewed
624
	 *
625
	 * This method is filtered by payment gateways in order to return true on subscriptions
626
	 * that can be renewed manually
627
	 *
628
	 * @since  2.5
629
	 * @return bool
630
	 */
631
	public function can_renew() {
632
633
		return apply_filters( 'wpinv_subscription_can_renew', true, $this );
634
	}
635
636
	/**
637
	 * Retrieves the URL to renew a subscription
638
	 *
639
	 * @since  2.5
640
	 * @return string
641
	 */
642
	public function get_renew_url() {
643
644
		$url = wp_nonce_url( add_query_arg( array( 'wpinv_action' => 'renew_subscription', 'sub_id' => $this->id ) ), 'wpinv-recurring-renew' );
645
646
		return apply_filters( 'wpinv_subscription_renew_url', $url, $this );
647
	}
648
649
	/**
650
	 * Determines if subscription can have their payment method updated
651
	 *
652
	 * @since  1.0.0
653
	 * @return bool
654
	 */
655
	public function can_update() {
656
		return apply_filters( 'wpinv_subscription_can_update', false, $this );
657
	}
658
659
	/**
660
	 * Retrieves the URL to update subscription
661
	 *
662
	 * @since  1.0.0
663
	 * @return void
664
	 */
665
	public function get_update_url() {
666
667
		$url = add_query_arg( array( 'action' => 'update', 'subscription_id' => $this->id ) );
668
669
		return apply_filters( 'wpinv_subscription_update_url', $url, $this );
0 ignored issues
show
Bug Best Practice introduced by
The expression return apply_filters('wp...date_url', $url, $this) also could return the type string which is incompatible with the documented return type void.
Loading history...
670
	}
671
672
	/**
673
	 * Determines if subscription is active
674
	 *
675
	 * @since  1.0.0
676
	 * @return void
677
	 */
678
	public function is_active() {
679
680
		$ret = false;
681
682
		if( ! $this->is_expired() && ( $this->status == 'active' || $this->status == 'cancelled' || $this->status == 'trialling' ) ) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->is_expired() targeting WPInv_Subscription::is_expired() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
683
			$ret = true;
684
		}
685
686
		return apply_filters( 'wpinv_subscription_is_active', $ret, $this->id, $this );
0 ignored issues
show
Bug Best Practice introduced by
The expression return apply_filters('wp...$ret, $this->id, $this) also could return the type boolean which is incompatible with the documented return type void.
Loading history...
687
688
	}
689
690
	/**
691
	 * Determines if subscription is expired
692
	 *
693
	 * @since  1.0.0
694
	 * @return void
695
	 */
696
	public function is_expired() {
697
698
		$ret = false;
699
700
		if ( $this->status == 'expired' ) {
701
702
			$ret = true;
703
704
		} elseif( 'active' === $this->status || 'cancelled' === $this->status || $this->status == 'trialling'  ) {
705
706
			$ret        = false;
707
			$expiration = $this->get_expiration_time();
708
709
			if( $expiration && strtotime( 'NOW', current_time( 'timestamp' ) ) > $expiration ) {
710
				$ret = true;
711
712
				if ( 'active' === $this->status || $this->status == 'trialling'  ) {
713
					$this->expire();
714
				}
715
			}
716
717
		}
718
719
		return apply_filters( 'wpinv_subscription_is_expired', $ret, $this->id, $this );
0 ignored issues
show
Bug Best Practice introduced by
The expression return apply_filters('wp...$ret, $this->id, $this) also could return the type boolean which is incompatible with the documented return type void.
Loading history...
720
721
	}
722
723
	/**
724
	 * Retrieves the expiration date
725
	 *
726
	 * @since  1.0.0
727
	 * @return string
728
	 */
729
	public function get_expiration() {
730
		return $this->expiration;
731
	}
732
733
	/**
734
	 * Retrieves the expiration date in a timestamp
735
	 *
736
	 * @since  1.0.0
737
	 * @return int
738
	 */
739
	public function get_expiration_time() {
740
		return strtotime( $this->expiration, current_time( 'timestamp' ) );
741
	}
742
743
	/**
744
	 * Retrieves the subscription status
745
	 *
746
	 * @since  1.0.0
747
	 * @return int
748
	 */
749
	public function get_status() {
750
751
		// Monitor for page load delays on pages with large subscription lists (IE: Subscriptions table in admin)
752
		$this->is_expired();
753
		return $this->status;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->status returns the type string which is incompatible with the documented return type integer.
Loading history...
754
	}
755
756
	/**
757
	 * Retrieves the subscription status label
758
	 *
759
	 * @since  1.0.0
760
	 * @return int
761
	 */
762
	public function get_status_label() {
763
764
		switch( $this->get_status() ) {
765
			case 'active' :
766
				$status = __( 'Active', 'invoicing' );
767
				break;
768
769
			case 'cancelled' :
770
				$status = __( 'Cancelled', 'invoicing' );
771
				break;
772
773
			case 'expired' :
774
				$status = __( 'Expired', 'invoicing' );
775
				break;
776
777
			case 'pending' :
778
				$status = __( 'Pending', 'invoicing' );
779
				break;
780
781
			case 'failing' :
782
				$status = __( 'Failing', 'invoicing' );
783
				break;
784
785
			case 'trialling' :
786
				$status = __( 'Trialling', 'invoicing' );
787
				break;
788
789
			case 'completed' :
790
				$status = __( 'Completed', 'invoicing' );
791
				break;
792
793
			default:
794
				$status = ucfirst( $this->get_status() );
795
				break;
796
		}
797
798
		return $status;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $status returns the type string which is incompatible with the documented return type integer.
Loading history...
799
	}
800
801
    /**
802
     * Retrieves the subscription status label
803
     *
804
     * @since  1.0.0
805
     * @return int
806
     */
807
    public function get_status_label_html() {
808
809
        switch( $get_status = $this->get_status() ) {
810
            case 'active' :
811
                $status = __( 'Active', 'invoicing' );
812
                $class = 'label-info';
813
                break;
814
815
            case 'cancelled' :
816
                $status = __( 'Cancelled', 'invoicing' );
817
                $class = 'label-danger';
818
                break;
819
820
            case 'expired' :
821
                $status = __( 'Expired', 'invoicing' );
822
                $class = 'label-default';
823
                break;
824
825
            case 'pending' :
826
                $status = __( 'Pending', 'invoicing' );
827
                $class = 'label-primary';
828
                break;
829
830
            case 'failing' :
831
                $status = __( 'Failing', 'invoicing' );
832
                $class = 'label-danger';
833
                break;
834
835
            case 'trialling' :
836
                $status = __( 'Trialling', 'invoicing' );
837
                $class = 'label-info';
838
                break;
839
840
            case 'completed' :
841
                $status = __( 'Completed', 'invoicing' );
842
                $class = 'label-success';
843
                break;
844
845
            default:
846
                $status = ucfirst( $this->get_status() );
847
                $class = 'label-default';
848
                break;
849
        }
850
851
        $label = '<span class="sub-status label label-sub-' . $get_status . ' ' . $class . '">' . $status . '</span>';
852
853
        return apply_filters( 'wpinv_subscription_status_label_html', $label, $get_status, $status );
0 ignored issues
show
Bug Best Practice introduced by
The expression return apply_filters('wp..., $get_status, $status) also could return the type string which is incompatible with the documented return type integer.
Loading history...
854
    }
855
856
    /**
857
     * Determines if a payment exists with the specified transaction ID
858
     *
859
     * @since  2.4
860
     * @param  string $txn_id The transaction ID from the merchant processor
861
     * @return bool
862
     */
863
    public function payment_exists( $txn_id = '' ) {
864
        global $wpdb;
865
866
        if ( empty( $txn_id ) ) {
867
            return false;
868
        }
869
870
        $txn_id = esc_sql( $txn_id );
871
872
        $purchase = $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wpinv_transaction_id' AND meta_value = '{$txn_id}' LIMIT 1" );
873
874
        if ( $purchase != null ) {
875
            return true;
876
        }
877
878
        return false;
879
    }
880
881
}
882