Passed
Pull Request — master (#118)
by
unknown
04:20
created

WPInv_Subscription::get_expiration_time()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
40
	 */
41
	function __construct( $_id_or_object = 0, $_by_profile_id = false ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
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 introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
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
It seems like $_id_or_object defined by $_sub on line 53 can also be of type object; however, WPInv_Subscription::setup_subscription() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
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;
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;
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;
96
	}
97
98
	/**
99
	 * Magic __get function to dispatch a call to retrieve a private property
100
	 *
101
	 * @since 1.0.0
102
	 */
103 View Code Duplication
	public function __get( $key ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
		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 );
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
202
		return $this->parent_payment_id;
203
204
	}
205
206
	/**
207
	 * Retrieve renewal payments for a subscription
208
	 *
209
	 * @since  1.0.0
210
	 * @return array
211
	 */
212
	public function get_child_payments() {
213
214
		$payments = get_posts( array(
215
			'post_parent'    => (int) $this->parent_payment_id,
216
			'posts_per_page' => '999',
217
			'post_status'    => array( 'publish', 'wpi-processing', 'wpi-renewal' ),
218
			'post_type'      => 'wpi_invoice'
219
		) );
220
221
		return $payments;
222
223
	}
224
225
	/**
226
	 * Counts the number of payments made to the subscription
227
	 *
228
	 * @since  2.4
229
	 * @return int
230
	 */
231
	public function get_total_payments() {
232
233
		return count( $this->get_child_payments() ) + 1;
234
235
	}
236
237
	/**
238
	 * Returns the number of times the subscription has been billed
239
	 *
240
	 * @since  2.6
241
	 * @return int
242
	 */
243
	public function get_times_billed() {
244
245
		$times_billed = $this->get_total_payments();
246
247
		if( ! empty( $this->trial_period ) ) {
248
			$times_billed -= 1;
249
		}
250
251
		return $times_billed;
252
253
	}
254
255
    /**
256
     * Records a new payment on the subscription
257
     *
258
     * @since  2.4
259
     * @param  array $args Array of values for the payment, including amount and transaction ID
260
     * @return bool
261
     */
262
    public function add_payment( $args = array() ) {
263
264
        $args = wp_parse_args( $args, array(
265
            'amount'         => '',
266
            'transaction_id' => '',
267
            'gateway'        => ''
268
        ) );
269
270
        if ( $this->payment_exists( $args['transaction_id'] ) ) {
271
            return false;
272
        }
273
274
        if(!$this->parent_payment_id){
275
            return false;
276
        }
277
278
        $invoice = new WPInv_Invoice($this->parent_payment_id);
0 ignored issues
show
Documentation introduced by
$this->parent_payment_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
279
        $invoice->ID = $invoice->title = $invoice->number ='';
0 ignored issues
show
Documentation Bug introduced by
The property $ID was declared of type integer, but $invoice->title = $invoice->number = '' is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
280
        $invoice->parent_invoice = $this->parent_payment_id;
281
        $invoice->save();
282
283
        do_action( 'wpinv_recurring_add_subscription_payment', $invoice, $this );
284
        do_action( 'wpinv_recurring_record_payment', $invoice->ID, $this->parent_payment_id, $args['amount'], $args['transaction_id'] );
285
286
        return $invoice->ID;
287
    }
288
289
	/**
290
	 * Retrieves the transaction ID from the subscription
291
	 *
292
	 * @since  1.0.0
293
	 * @return bool
294
	 */
295
	public function get_transaction_id() {
296
297
		if( empty( $this->transaction_id ) ) {
298
299
			$txn_id = wpinv_get_payment_transaction_id( $this->parent_payment_id );
300
301
			if( ! empty( $txn_id ) && (int) $this->parent_payment_id !== (int) $txn_id ) {
302
				$this->set_transaction_id( $txn_id );
303
			}
304
305
		}
306
307
		return $this->transaction_id;
308
309
	}
310
311
	/**
312
	 * Stores the transaction ID for the subscription purchase
313
	 *
314
	 * @since  1.0.0.4
315
	 * @return bool
316
	 */
317
	public function set_transaction_id( $txn_id = '' ) {
318
		$this->update( array( 'transaction_id' => $txn_id ) );
319
		$this->transaction_id = $txn_id;
320
	}
321
322
	/**
323
	 * Renews a subscription
324
	 *
325
	 * @since  1.0.0
326
	 * @return bool
327
	 */
328
	public function renew() {
329
330
		$expires = $this->get_expiration_time();
331
332
333
		// Determine what date to use as the start for the new expiration calculation
334
		if( $expires > current_time( 'timestamp' ) && $this->is_active() ) {
335
336
			$base_date  = $expires;
337
338
		} else {
339
340
			$base_date  = current_time( 'timestamp' );
341
342
		}
343
344
		$last_day = cal_days_in_month( CAL_GREGORIAN, date( 'n', $base_date ), date( 'Y', $base_date ) );
345
346
347
		$frequency = isset($this->frequency) ? $this->frequency : 1;
0 ignored issues
show
Documentation introduced by
The property frequency does not exist on object<WPInv_Subscription>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
348
		$expiration = date( 'Y-m-d H:i:s', strtotime( '+' . $frequency . ' ' . $this->period  . ' 23:59:59', $base_date ) );
349
350
		if( date( 'j', $base_date ) == $last_day && 'day' != $this->period ) {
351
			$expiration = date( 'Y-m-d H:i:s', strtotime( $expiration . ' +2 days' ) );
352
		}
353
354
		$expiration  = apply_filters( 'wpinv_subscription_renewal_expiration', $expiration, $this->id, $this );
355
356
		do_action( 'wpinv_subscription_pre_renew', $this->id, $expiration, $this );
357
358
		$this->status = 'active';
359
		$times_billed = $this->get_times_billed();
360
361
		// Complete subscription if applicable
362
		if ( $this->bill_times > 0 && $times_billed >= $this->bill_times ) {
363
			$this->complete();
364
			$this->status = 'completed';
365
		}
366
367
		$args = array(
368
			'expiration' => $expiration,
369
			'status'     => $this->status,
370
		);
371
372
        $this->subs_db->update( $this->id, $args );
373
374
		do_action( 'wpinv_subscription_post_renew', $this->id, $expiration, $this );
375
		do_action( 'wpinv_recurring_set_subscription_status', $this->id, $this->status, $this );
376
377
	}
378
379
	/**
380
	 * Marks a subscription as completed
381
	 *
382
	 * Subscription is completed when the number of payments matches the billing_times field
383
	 *
384
	 * @since  1.0.0
385
	 * @return void
386
	 */
387
	public function complete() {
388
389
		// Only mark a subscription as complete if it's not already cancelled.
390
		if ( 'cancelled' === $this->status ) {
391
			return;
392
		}
393
394
		$args = array(
395
			'status' => 'completed'
396
		);
397
398
		if( $this->subs_db->update( $this->id, $args ) ) {
399
400
			$this->status = 'completed';
401
402
			do_action( 'wpinv_subscription_completed', $this->id, $this );
403
404
		}
405
406
	}
407
408
	/**
409
	 * Marks a subscription as expired
410
	 *
411
	 * Subscription is completed when the billing times is reached
412
	 *
413
	 * @since  1.0.0
414
	 * @param  $check_expiration bool True if expiration date should be checked with merchant processor before expiring
415
	 * @return void
416
	 */
417
	public function expire( $check_expiration = false ) {
418
419
		$expiration = $this->expiration;
420
421
		if( $check_expiration && $this->check_expiration() ) {
0 ignored issues
show
Bug introduced by
The method check_expiration() does not seem to exist on object<WPInv_Subscription>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
422
423
			// check_expiration() updates $this->expiration so compare to $expiration above
424
425
			if( $expiration < $this->get_expiration() && current_time( 'timestamp' ) < $this->get_expiration_time() ) {
426
427
				return false; // Do not mark as expired since real expiration date is in the future
428
			}
429
430
		}
431
432
		$args = array(
433
			'status' => 'expired'
434
		);
435
436
		if( $this->subs_db->update( $this->id, $args ) ) {
437
438
			$this->status = 'expired';
439
440
			do_action( 'wpinv_subscription_expired', $this->id, $this );
441
442
		}
443
444
	}
445
446
	/**
447
	 * Marks a subscription as failing
448
	 *
449
	 * @since  2.4.2
450
	 * @return void
451
	 */
452
	public function failing() {
453
454
		$args = array(
455
			'status' => 'failing'
456
		);
457
458
		if( $this->subs_db->update( $this->id, $args ) ) {
459
460
			$this->status = 'failing';
461
462
			do_action( 'wpinv_subscription_failing', $this->id, $this );
463
464
465
		}
466
467
	}
468
469
	/**
470
	 * Marks a subscription as cancelled
471
	 *
472
	 * @since  1.0.0
473
	 * @return void
474
	 */
475
	public function cancel() {
476
477
		if( 'cancelled' === $this->status ) {
478
			return; // Already cancelled
479
		}
480
481
		$args = array(
482
			'status' => 'cancelled'
483
		);
484
485
		if( $this->subs_db->update( $this->id, $args ) ) {
486
487 View Code Duplication
            if( is_user_logged_in() ) {
488
489
                $userdata = get_userdata( get_current_user_id() );
490
                $user     = $userdata->display_name;
491
492
            } else {
493
494
                $user = __( 'gateway', 'invoicing' );
495
496
            }
497
498
            $note = sprintf( __( 'Subscription for Invoice #%d cancelled by %s', 'invoicing' ), $this->parent_payment_id, $user );
499
            wpinv_insert_payment_note( $this->parent_payment_id, $note, '', '', true );
0 ignored issues
show
Documentation introduced by
'' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
500
501
		    $this->status = 'cancelled';
502
503
			do_action( 'wpinv_subscription_cancelled', $this->id, $this );
504
505
506
		}
507
508
	}
509
510
	/**
511
	 * Determines if subscription can be cancelled
512
	 *
513
	 * This method is filtered by payment gateways in order to return true on subscriptions
514
	 * that can be cancelled with a profile ID through the merchant processor
515
	 *
516
	 * @since  1.0.0
517
	 * @return bool
518
	 */
519
	public function can_cancel() {
520
        $ret = false;
521
	    if( $this->gateway === 'manual' || in_array( $this->status, $this->get_cancellable_statuses() ) ) {
522
            $ret = true;
523
        }
524
		return apply_filters( 'wpinv_subscription_can_cancel', $ret, $this );
525
	}
526
527
    /**
528
     * Returns an array of subscription statuses that can be cancelled
529
     *
530
     * @access      public
531
     * @since       1.0.0
532
     * @return      array
533
     */
534
    public function get_cancellable_statuses() {
535
        return apply_filters( 'wpinv_recurring_cancellable_statuses', array( 'active', 'trialling', 'failing' ) );
536
    }
537
538
	/**
539
	 * Retrieves the URL to cancel subscription
540
	 *
541
	 * @since  1.0.0
542
	 * @return string
543
	 */
544
	public function get_cancel_url() {
545
546
		$url = wp_nonce_url( add_query_arg( array( 'wpinv_action' => 'cancel_subscription', 'sub_id' => $this->id ) ), 'wpinv-recurring-cancel' );
547
548
		return apply_filters( 'wpinv_subscription_cancel_url', $url, $this );
549
	}
550
551
	/**
552
	 * Determines if subscription can be manually renewed
553
	 *
554
	 * This method is filtered by payment gateways in order to return true on subscriptions
555
	 * that can be renewed manually
556
	 *
557
	 * @since  2.5
558
	 * @return bool
559
	 */
560
	public function can_renew() {
561
562
		return apply_filters( 'wpinv_subscription_can_renew', true, $this );
563
	}
564
565
	/**
566
	 * Retrieves the URL to renew a subscription
567
	 *
568
	 * @since  2.5
569
	 * @return string
570
	 */
571
	public function get_renew_url() {
572
573
		$url = wp_nonce_url( add_query_arg( array( 'wpinv_action' => 'renew_subscription', 'sub_id' => $this->id ) ), 'wpinv-recurring-renew' );
574
575
		return apply_filters( 'wpinv_subscription_renew_url', $url, $this );
576
	}
577
578
	/**
579
	 * Determines if subscription can have their payment method updated
580
	 *
581
	 * @since  1.0.0
582
	 * @return bool
583
	 */
584
	public function can_update() {
585
		return apply_filters( 'wpinv_subscription_can_update', false, $this );
586
	}
587
588
	/**
589
	 * Retrieves the URL to update subscription
590
	 *
591
	 * @since  1.0.0
592
	 * @return void
593
	 */
594
	public function get_update_url() {
595
596
		$url = add_query_arg( array( 'action' => 'update', 'subscription_id' => $this->id ) );
597
598
		return apply_filters( 'wpinv_subscription_update_url', $url, $this );
599
	}
600
601
	/**
602
	 * Determines if subscription is active
603
	 *
604
	 * @since  1.0.0
605
	 * @return void
606
	 */
607
	public function is_active() {
608
609
		$ret = false;
610
611
		if( ! $this->is_expired() && ( $this->status == 'active' || $this->status == 'cancelled' || $this->status == 'trialling' ) ) {
612
			$ret = true;
613
		}
614
615
		return apply_filters( 'wpinv_subscription_is_active', $ret, $this->id, $this );
616
617
	}
618
619
	/**
620
	 * Determines if subscription is expired
621
	 *
622
	 * @since  1.0.0
623
	 * @return void
624
	 */
625
	public function is_expired() {
626
627
		$ret = false;
628
629
		if ( $this->status == 'expired' ) {
630
631
			$ret = true;
632
633
		} elseif( 'active' === $this->status || 'cancelled' === $this->status || $this->status == 'trialling'  ) {
634
635
			$ret        = false;
636
			$expiration = $this->get_expiration_time();
637
638
			if( $expiration && strtotime( 'NOW', current_time( 'timestamp' ) ) > $expiration ) {
639
				$ret = true;
640
641
				if ( 'active' === $this->status || $this->status == 'trialling'  ) {
642
					$this->expire();
643
				}
644
			}
645
646
		}
647
648
		return apply_filters( 'wpinv_subscription_is_expired', $ret, $this->id, $this );
649
650
	}
651
652
	/**
653
	 * Retrieves the expiration date
654
	 *
655
	 * @since  1.0.0
656
	 * @return string
657
	 */
658
	public function get_expiration() {
659
		return $this->expiration;
660
	}
661
662
	/**
663
	 * Retrieves the expiration date in a timestamp
664
	 *
665
	 * @since  1.0.0
666
	 * @return int
667
	 */
668
	public function get_expiration_time() {
669
		return strtotime( $this->expiration, current_time( 'timestamp' ) );
670
	}
671
672
	/**
673
	 * Retrieves the subscription status
674
	 *
675
	 * @since  1.0.0
676
	 * @return int
677
	 */
678
	public function get_status() {
679
680
		// Monitor for page load delays on pages with large subscription lists (IE: Subscriptions table in admin)
681
		$this->is_expired();
682
		return $this->status;
683
	}
684
685
	/**
686
	 * Retrieves the subscription status label
687
	 *
688
	 * @since  1.0.0
689
	 * @return int
690
	 */
691
	public function get_status_label() {
692
693
		switch( $this->get_status() ) {
694
			case 'active' :
695
				$status = __( 'Active', 'invoicing' );
696
				break;
697
698
			case 'cancelled' :
699
				$status = __( 'Cancelled', 'invoicing' );
700
				break;
701
702
			case 'expired' :
703
				$status = __( 'Expired', 'invoicing' );
704
				break;
705
706
			case 'pending' :
707
				$status = __( 'Pending', 'invoicing' );
708
				break;
709
710
			case 'failing' :
711
				$status = __( 'Failing', 'invoicing' );
712
				break;
713
714
			case 'trialling' :
715
				$status = __( 'Trialling', 'invoicing' );
716
				break;
717
718
			case 'completed' :
719
				$status = __( 'Completed', 'invoicing' );
720
				break;
721
722
			default:
723
				$status = ucfirst( $this->get_status() );
724
				break;
725
		}
726
727
		return $status;
728
	}
729
730
    /**
731
     * Retrieves the subscription status label
732
     *
733
     * @since  1.0.0
734
     * @return int
735
     */
736
    public function get_status_label_html() {
737
738
        switch( $get_status = $this->get_status() ) {
739
            case 'active' :
740
                $status = __( 'Active', 'invoicing' );
741
                $class = 'label-info';
742
                break;
743
744
            case 'cancelled' :
745
                $status = __( 'Cancelled', 'invoicing' );
746
                $class = 'label-danger';
747
                break;
748
749
            case 'expired' :
750
                $status = __( 'Expired', 'invoicing' );
751
                $class = 'label-default';
752
                break;
753
754
            case 'pending' :
755
                $status = __( 'Pending', 'invoicing' );
756
                $class = 'label-primary';
757
                break;
758
759
            case 'failing' :
760
                $status = __( 'Failing', 'invoicing' );
761
                $class = 'label-danger';
762
                break;
763
764
            case 'trialling' :
765
                $status = __( 'Trialling', 'invoicing' );
766
                $class = 'label-info';
767
                break;
768
769
            case 'completed' :
770
                $status = __( 'Completed', 'invoicing' );
771
                $class = 'label-success';
772
                break;
773
774
            default:
775
                $status = ucfirst( $this->get_status() );
776
                $class = 'label-default';
777
                break;
778
        }
779
780
        $label = '<span class="sub-status label label-sub-' . $get_status . ' ' . $class . '">' . $status . '</span>';
781
782
        return apply_filters( 'wpinv_subscription_status_label_html', $label, $get_status, $status );
783
    }
784
785
    /**
786
     * Determines if a payment exists with the specified transaction ID
787
     *
788
     * @since  2.4
789
     * @param  string $txn_id The transaction ID from the merchant processor
790
     * @return bool
791
     */
792
    public function payment_exists( $txn_id = '' ) {
793
        global $wpdb;
794
795
        if ( empty( $txn_id ) ) {
796
            return false;
797
        }
798
799
        $txn_id = esc_sql( $txn_id );
800
801
        $purchase = $wpdb->get_var( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wpinv_transaction_id' AND meta_value = '{$txn_id}' LIMIT 1" );
802
803
        if ( $purchase != null ) {
804
            return true;
805
        }
806
807
        return false;
808
    }
809
810
}
811