Passed
Pull Request — master (#410)
by Brian
04:58
created

WPInv_Invoice::set_country()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 2
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * Contains the invoice class.
4
 *
5
 * @since 1.0.19
6
 * @package Invoicing
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Invoice class.
13
 */
14
class WPInv_Invoice extends GetPaid_Data {
15
16
    /**
17
	 * Which data store to load.
18
	 *
19
	 * @var string
20
	 */
21
    protected $data_store_name = 'invoice';
22
23
    /**
24
	 * This is the name of this object type.
25
	 *
26
	 * @var string
27
	 */
28
    protected $object_type = 'invoice';
29
30
    /**
31
	 * Item Data array. This is the core item data exposed in APIs.
32
	 *
33
	 * @since 1.0.19
34
	 * @var array
35
	 */
36
	protected $data = array(
37
		'parent_id'            => 0,
38
		'status'               => 'wpi-pending',
39
		'version'              => '',
40
		'date_created'         => null,
41
        'date_modified'        => null,
42
        'due_date'             => null,
43
        'completed_date'       => null,
44
        'number'               => '',
45
        'title'                => '',
46
        'path'                 => '',
47
        'key'                  => '',
48
        'description'          => '',
49
        'author'               => 1,
50
        'type'                 => 'invoice',
51
        'post_type'            => 'wpi_invoice',
52
        'mode'                 => 'live',
53
        'user_ip'              => null,
54
        'first_name'           => null,
55
        'last_name'            => null,
56
        'phone'                => null,
57
        'email'                => null,
58
        'country'              => null,
59
        'city'                 => null,
60
        'state'                => null,
61
        'zip'                  => null,
62
        'company'              => null,
63
        'vat_number'           => null,
64
        'vat_rate'             => null,
65
        'address'              => null,
66
        'address_confirmed'    => false,
67
        'subtotal'             => 0,
68
        'total_discount'       => 0,
69
        'total_tax'            => 0,
70
        'total_fees'           => 0,
71
        'fees'                 => array(),
72
        'discounts'            => array(),
73
        'taxes'                => array(),
74
        'items'                => array(),
75
        'payment_form'         => 1,
76
        'submission_id'        => null,
77
        'discount_code'        => null,
78
        'gateway'              => 'none',
79
        'transaction_id'       => '',
80
        'currency'             => '',
81
        'disable_taxes'        => false,
82
		'subscription_id'      => null,
83
		'remote_subscription_id' => null,
84
		'is_viewed'            => false,
85
		'email_cc'             => '',
86
		'template'             => 'quantity', // hours, amount only
87
    );
88
89
    /**
90
	 * Stores meta in cache for future reads.
91
	 *
92
	 * A group must be set to to enable caching.
93
	 *
94
	 * @var string
95
	 */
96
	protected $cache_group = 'getpaid_invoices';
97
98
    /**
99
     * Stores a reference to the original WP_Post object
100
     *
101
     * @var WP_Post
102
     */
103
    protected $post = null;
104
105
    /**
106
     * Stores a reference to the recurring item id instead of looping through the items.
107
     *
108
     * @var int
109
     */
110
	protected $recurring_item = null;
111
112
	/**
113
     * Stores an array of item totals.
114
	 *
115
	 * e.g $totals['discount'] = array(
116
	 * 		'initial'   => 10,
117
	 * 		'recurring' => 10,
118
	 * )
119
     *
120
     * @var array
121
     */
122
	protected $totals = array();
123
124
	/**
125
	 * Stores the status transition information.
126
	 *
127
	 * @since 1.0.19
128
	 * @var bool
129
	 */
130
	protected $status_transition = false;
131
132
    /**
133
	 * Get the invoice if ID is passed, otherwise the invoice is new and empty.
134
	 *
135
	 * @param  int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object to read.
136
	 */
137
    public function __construct( $invoice = false ) {
138
139
        parent::__construct( $invoice );
0 ignored issues
show
Bug introduced by
It seems like $invoice can also be of type false and string; however, parameter $read of GetPaid_Data::__construct() does only seem to accept array|integer|object, maybe add an additional type check? ( Ignorable by Annotation )

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

139
        parent::__construct( /** @scrutinizer ignore-type */ $invoice );
Loading history...
140
141
		if ( ! empty( $invoice ) && is_numeric( $invoice ) && getpaid_is_invoice_post_type( get_post_type( $invoice ) ) ) {
0 ignored issues
show
Bug introduced by
It seems like $invoice can also be of type string; however, parameter $post of get_post_type() does only seem to accept WP_Post|integer|null, maybe add an additional type check? ( Ignorable by Annotation )

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

141
		if ( ! empty( $invoice ) && is_numeric( $invoice ) && getpaid_is_invoice_post_type( get_post_type( /** @scrutinizer ignore-type */ $invoice ) ) ) {
Loading history...
142
			$this->set_id( $invoice );
0 ignored issues
show
Bug introduced by
It seems like $invoice can also be of type string; however, parameter $id of GetPaid_Data::set_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

142
			$this->set_id( /** @scrutinizer ignore-type */ $invoice );
Loading history...
143
		} elseif ( $invoice instanceof self ) {
144
			$this->set_id( $invoice->get_id() );
145
		} elseif ( ! empty( $invoice->ID ) ) {
146
			$this->set_id( $invoice->ID );
147
		} elseif ( is_array( $invoice ) ) {
0 ignored issues
show
introduced by
The condition is_array($invoice) is always false.
Loading history...
148
			$this->set_props( $invoice );
149
150
			if ( isset( $invoice['ID'] ) ) {
151
				$this->set_id( $invoice['ID'] );
152
			}
153
154
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'key' ) ) {
0 ignored issues
show
Bug introduced by
It seems like $invoice can also be of type false; however, parameter $value of WPInv_Invoice::get_invoice_id_by_field() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

154
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( /** @scrutinizer ignore-type */ $invoice, 'key' ) ) {
Loading history...
155
			$this->set_id( $invoice_id );
156
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'number' ) ) {
157
			$this->set_id( $invoice_id );
158
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'transaction_id' ) ) {
159
			$this->set_id( $invoice_id );
160
		}else {
161
			$this->set_object_read( true );
162
		}
163
164
        // Load the datastore.
165
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
166
167
		if ( $this->get_id() > 0 ) {
168
            $this->post = get_post( $this->get_id() );
169
            $this->ID   = $this->get_id();
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
170
			$this->data_store->read( $this );
171
        }
172
173
    }
174
175
    /**
176
	 * Given an invoice key/number, it returns its id.
177
	 *
178
	 *
179
	 * @static
180
	 * @param string $value The invoice key or number
181
	 * @param string $field Either key, transaction_id or number.
182
	 * @since 1.0.15
183
	 * @return int
184
	 */
185
	public static function get_invoice_id_by_field( $value, $field = 'key' ) {
186
        global $wpdb;
187
188
		// Trim the value.
189
		$value = trim( $value );
190
191
		if ( empty( $value ) ) {
192
			return 0;
193
		}
194
195
        // Valid fields.
196
        $fields = array( 'key', 'number', 'transaction_id' );
197
198
		// Ensure a field has been passed.
199
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
200
			return 0;
201
		}
202
203
		// Maybe retrieve from the cache.
204
		$invoice_id   = wp_cache_get( $value, "getpaid_invoice_{$field}s_to_invoice_ids" );
205
		if ( false !== $invoice_id ) {
206
			return $invoice_id;
207
		}
208
209
        // Fetch from the db.
210
        $table       = $wpdb->prefix . 'getpaid_invoices';
211
        $invoice_id  = (int) $wpdb->get_var(
212
            $wpdb->prepare( "SELECT `post_id` FROM $table WHERE `$field`=%s LIMIT 1", $value )
213
        );
214
215
		// Update the cache with our data
216
		wp_cache_set( $value, $invoice_id, "getpaid_invoice_{$field}s_to_invoice_ids" );
217
218
		return $invoice_id;
219
    }
220
221
    /**
222
     * Checks if an invoice key is set.
223
     */
224
    public function _isset( $key ) {
225
        return isset( $this->data[$key] ) || method_exists( $this, "get_$key" );
226
    }
227
228
    /*
229
	|--------------------------------------------------------------------------
230
	| CRUD methods
231
	|--------------------------------------------------------------------------
232
	|
233
	| Methods which create, read, update and delete items from the database.
234
	|
235
    */
236
237
    /*
238
	|--------------------------------------------------------------------------
239
	| Getters
240
	|--------------------------------------------------------------------------
241
    */
242
243
    /**
244
	 * Get parent invoice ID.
245
	 *
246
	 * @since 1.0.19
247
	 * @param  string $context View or edit context.
248
	 * @return int
249
	 */
250
	public function get_parent_id( $context = 'view' ) {
251
		return (int) $this->get_prop( 'parent_id', $context );
252
    }
253
254
    /**
255
	 * Get parent invoice.
256
	 *
257
	 * @since 1.0.19
258
	 * @return WPInv_Invoice
259
	 */
260
    public function get_parent_payment() {
261
        return new WPInv_Invoice( $this->get_parent_id() );
262
    }
263
264
    /**
265
	 * Alias for self::get_parent_payment().
266
	 *
267
	 * @since 1.0.19
268
	 * @return WPInv_Invoice
269
	 */
270
    public function get_parent() {
271
        return $this->get_parent_payment();
272
    }
273
274
    /**
275
	 * Get invoice status.
276
	 *
277
	 * @since 1.0.19
278
	 * @param  string $context View or edit context.
279
	 * @return string
280
	 */
281
	public function get_status( $context = 'view' ) {
282
		return $this->get_prop( 'status', $context );
283
	}
284
	
285
	/**
286
	 * Retrieves an array of possible invoice statuses.
287
	 *
288
	 * @since 1.0.19
289
	 * @return array
290
	 */
291
	public function get_all_statuses() {
292
293
		$statuses = wpinv_get_invoice_statuses( true, true, $this );
294
295
		// For backwards compatibility.
296
		if ( $this->is_quote() && class_exists( 'Wpinv_Quotes_Shared' ) ) {
297
            $statuses = Wpinv_Quotes_Shared::wpinv_get_quote_statuses();
0 ignored issues
show
Bug introduced by
The type Wpinv_Quotes_Shared 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...
298
		}
299
300
		return $statuses;
301
    }
302
303
    /**
304
	 * Get invoice status nice name.
305
	 *
306
	 * @since 1.0.19
307
	 * @return string
308
	 */
309
    public function get_status_nicename() {
310
		$statuses = $this->get_all_statuses();
311
312
        $status = isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : $this->get_status();
313
314
        return apply_filters( 'wpinv_get_invoice_status_nicename', $status, $this );
315
    }
316
317
	/**
318
     * Retrieves the invoice status label html
319
     *
320
     * @since  1.0.0
321
     * @return string
322
     */
323
    public function get_status_label_html() {
324
325
		$status_label = sanitize_text_field( $this->get_status_nicename() );
326
		$status       = sanitize_html_class( $this->get_status() );
327
328
		return "<span class='bsui'><span class='d-inline-block py-2 px-3 rounded getpaid-invoice-status-$status'>$status_label</span></span>";
329
	}
330
331
    /**
332
	 * Get plugin version when the invoice was created.
333
	 *
334
	 * @since 1.0.19
335
	 * @param  string $context View or edit context.
336
	 * @return string
337
	 */
338
	public function get_version( $context = 'view' ) {
339
		return $this->get_prop( 'version', $context );
340
	}
341
342
	/**
343
	 * @deprecated
344
	 */
345
	public function get_invoice_date( $formatted = true ) {
346
        $date_completed = $this->get_date_completed();
347
        $invoice_date   = $date_completed != '0000-00-00 00:00:00' ? $date_completed : '';
348
349
        if ( $invoice_date == '' ) {
350
            $date_created   = $this->get_date_created();
351
            $invoice_date   = $date_created != '0000-00-00 00:00:00' ? $date_created : '';
352
        }
353
354
        if ( $formatted && $invoice_date ) {
355
            $invoice_date   = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date ) );
0 ignored issues
show
Bug introduced by
It seems like get_option('date_format') can also be of type false; however, parameter $format of date_i18n() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

355
            $invoice_date   = date_i18n( /** @scrutinizer ignore-type */ get_option( 'date_format' ), strtotime( $invoice_date ) );
Loading history...
356
        }
357
358
        return apply_filters( 'wpinv_get_invoice_date', $invoice_date, $formatted, $this->get_id(), $this );
359
    }
360
361
    /**
362
	 * Get date when the invoice was created.
363
	 *
364
	 * @since 1.0.19
365
	 * @param  string $context View or edit context.
366
	 * @return string
367
	 */
368
	public function get_date_created( $context = 'view' ) {
369
		return $this->get_prop( 'date_created', $context );
370
	}
371
	
372
	/**
373
	 * Alias for self::get_date_created().
374
	 *
375
	 * @since 1.0.19
376
	 * @param  string $context View or edit context.
377
	 * @return string
378
	 */
379
	public function get_created_date( $context = 'view' ) {
380
		return $this->get_date_created( $context );
381
    }
382
383
    /**
384
	 * Get GMT date when the invoice was created.
385
	 *
386
	 * @since 1.0.19
387
	 * @param  string $context View or edit context.
388
	 * @return string
389
	 */
390
	public function get_date_created_gmt( $context = 'view' ) {
391
        $date = $this->get_date_created( $context );
392
393
        if ( $date ) {
394
            $date = get_gmt_from_date( $date );
395
        }
396
		return $date;
397
    }
398
399
    /**
400
	 * Get date when the invoice was last modified.
401
	 *
402
	 * @since 1.0.19
403
	 * @param  string $context View or edit context.
404
	 * @return string
405
	 */
406
	public function get_date_modified( $context = 'view' ) {
407
		return $this->get_prop( 'date_modified', $context );
408
	}
409
410
	/**
411
	 * Alias for self::get_date_modified().
412
	 *
413
	 * @since 1.0.19
414
	 * @param  string $context View or edit context.
415
	 * @return string
416
	 */
417
	public function get_modified_date( $context = 'view' ) {
418
		return $this->get_date_modified( $context );
419
    }
420
421
    /**
422
	 * Get GMT date when the invoice was last modified.
423
	 *
424
	 * @since 1.0.19
425
	 * @param  string $context View or edit context.
426
	 * @return string
427
	 */
428
	public function get_date_modified_gmt( $context = 'view' ) {
429
        $date = $this->get_date_modified( $context );
430
431
        if ( $date ) {
432
            $date = get_gmt_from_date( $date );
433
        }
434
		return $date;
435
    }
436
437
    /**
438
	 * Get the invoice due date.
439
	 *
440
	 * @since 1.0.19
441
	 * @param  string $context View or edit context.
442
	 * @return string
443
	 */
444
	public function get_due_date( $context = 'view' ) {
445
		return $this->get_prop( 'due_date', $context );
446
    }
447
448
    /**
449
	 * Alias for self::get_due_date().
450
	 *
451
	 * @since 1.0.19
452
	 * @param  string $context View or edit context.
453
	 * @return string
454
	 */
455
	public function get_date_due( $context = 'view' ) {
456
		return $this->get_due_date( $context );
457
    }
458
459
    /**
460
	 * Get the invoice GMT due date.
461
	 *
462
	 * @since 1.0.19
463
	 * @param  string $context View or edit context.
464
	 * @return string
465
	 */
466
	public function get_due_date_gmt( $context = 'view' ) {
467
        $date = $this->get_due_date( $context );
468
469
        if ( $date ) {
470
            $date = get_gmt_from_date( $date );
471
        }
472
		return $date;
473
    }
474
475
    /**
476
	 * Alias for self::get_due_date_gmt().
477
	 *
478
	 * @since 1.0.19
479
	 * @param  string $context View or edit context.
480
	 * @return string
481
	 */
482
	public function get_gmt_date_due( $context = 'view' ) {
483
		return $this->get_due_date_gmt( $context );
484
    }
485
486
    /**
487
	 * Get date when the invoice was completed.
488
	 *
489
	 * @since 1.0.19
490
	 * @param  string $context View or edit context.
491
	 * @return string
492
	 */
493
	public function get_completed_date( $context = 'view' ) {
494
		return $this->get_prop( 'completed_date', $context );
495
    }
496
497
    /**
498
	 * Alias for self::get_completed_date().
499
	 *
500
	 * @since 1.0.19
501
	 * @param  string $context View or edit context.
502
	 * @return string
503
	 */
504
	public function get_date_completed( $context = 'view' ) {
505
		return $this->get_completed_date( $context );
506
    }
507
508
    /**
509
	 * Get GMT date when the invoice was was completed.
510
	 *
511
	 * @since 1.0.19
512
	 * @param  string $context View or edit context.
513
	 * @return string
514
	 */
515
	public function get_completed_date_gmt( $context = 'view' ) {
516
        $date = $this->get_completed_date( $context );
517
518
        if ( $date ) {
519
            $date = get_gmt_from_date( $date );
520
        }
521
		return $date;
522
    }
523
524
    /**
525
	 * Alias for self::get_completed_date_gmt().
526
	 *
527
	 * @since 1.0.19
528
	 * @param  string $context View or edit context.
529
	 * @return string
530
	 */
531
	public function get_gmt_completed_date( $context = 'view' ) {
532
		return $this->get_completed_date_gmt( $context );
533
    }
534
535
    /**
536
	 * Get the invoice number.
537
	 *
538
	 * @since 1.0.19
539
	 * @param  string $context View or edit context.
540
	 * @return string
541
	 */
542
	public function get_number( $context = 'view' ) {
543
        $number = $this->get_prop( 'number', $context );
544
545
        if ( empty( $number ) ) {
546
            $number = $this->generate_number();
547
            $this->set_number( $number );
548
        }
549
550
		return $number;
551
    }
552
553
    /**
554
	 * Get the invoice key.
555
	 *
556
	 * @since 1.0.19
557
	 * @param  string $context View or edit context.
558
	 * @return string
559
	 */
560
	public function get_key( $context = 'view' ) {
561
        $key = $this->get_prop( 'key', $context );
562
563
        if ( empty( $key ) ) {
564
            $key = $this->generate_key( $this->get_type() . '_' );
565
            $this->set_key( $key );
566
        }
567
568
		return $key;
569
    }
570
571
    /**
572
	 * Get the invoice type.
573
	 *
574
	 * @since 1.0.19
575
	 * @param  string $context View or edit context.
576
	 * @return string
577
	 */
578
	public function get_type( $context = 'view' ) {
579
        return $this->get_prop( 'type', $context );
580
	}
581
582
	/**
583
	 * @deprecated
584
	 */
585
	public function get_invoice_quote_type() {
586
        ucfirst( $this->get_type() );
587
    }
588
589
    /**
590
	 * Get the invoice post type.
591
	 *
592
	 * @since 1.0.19
593
	 * @param  string $context View or edit context.
594
	 * @return string
595
	 */
596
	public function get_post_type( $context = 'view' ) {
597
        return $this->get_prop( 'post_type', $context );
598
    }
599
600
    /**
601
	 * Get the invoice mode.
602
	 *
603
	 * @since 1.0.19
604
	 * @param  string $context View or edit context.
605
	 * @return string
606
	 */
607
	public function get_mode( $context = 'view' ) {
608
        return $this->get_prop( 'mode', $context );
609
    }
610
611
    /**
612
	 * Get the invoice path.
613
	 *
614
	 * @since 1.0.19
615
	 * @param  string $context View or edit context.
616
	 * @return string
617
	 */
618
	public function get_path( $context = 'view' ) {
619
        $path = $this->get_prop( 'path', $context );
620
621
        if ( empty( $path ) ) {
622
            $prefix = apply_filters( 'wpinv_post_name_prefix', 'inv-', $this->post_type );
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
623
            $path   = sanitize_title( $prefix . $this->get_id() );
624
        }
625
626
		return $path;
627
    }
628
629
    /**
630
	 * Get the invoice name/title.
631
	 *
632
	 * @since 1.0.19
633
	 * @param  string $context View or edit context.
634
	 * @return string
635
	 */
636
	public function get_name( $context = 'view' ) {
637
        return $this->get_prop( 'title', $context );
638
    }
639
640
    /**
641
	 * Alias of self::get_name().
642
	 *
643
	 * @since 1.0.19
644
	 * @param  string $context View or edit context.
645
	 * @return string
646
	 */
647
	public function get_title( $context = 'view' ) {
648
		return $this->get_name( $context );
649
    }
650
651
    /**
652
	 * Get the invoice description.
653
	 *
654
	 * @since 1.0.19
655
	 * @param  string $context View or edit context.
656
	 * @return string
657
	 */
658
	public function get_description( $context = 'view' ) {
659
		return $this->get_prop( 'description', $context );
660
    }
661
662
    /**
663
	 * Alias of self::get_description().
664
	 *
665
	 * @since 1.0.19
666
	 * @param  string $context View or edit context.
667
	 * @return string
668
	 */
669
	public function get_excerpt( $context = 'view' ) {
670
		return $this->get_description( $context );
671
    }
672
673
    /**
674
	 * Alias of self::get_description().
675
	 *
676
	 * @since 1.0.19
677
	 * @param  string $context View or edit context.
678
	 * @return string
679
	 */
680
	public function get_summary( $context = 'view' ) {
681
		return $this->get_description( $context );
682
    }
683
684
    /**
685
	 * Returns the user info.
686
	 *
687
	 * @since 1.0.19
688
     * @param  string $context View or edit context.
689
	 * @return array
690
	 */
691
    public function get_user_info( $context = 'view' ) {
692
693
        $user_info = array(
694
            'user_id'    => $this->get_user_id( $context ),
695
            'email'      => $this->get_email( $context ),
696
            'first_name' => $this->get_first_name( $context ),
697
            'last_name'  => $this->get_last_name( $context ),
698
            'address'    => $this->get_address( $context ),
699
            'phone'      => $this->get_phone( $context ),
700
            'city'       => $this->get_city( $context ),
701
            'country'    => $this->get_country( $context ),
702
            'state'      => $this->get_state( $context ),
703
            'zip'        => $this->get_zip( $context ),
704
            'company'    => $this->get_company( $context ),
705
            'vat_number' => $this->get_vat_number( $context ),
706
            'discount'   => $this->get_discount_code( $context ),
707
		);
708
709
		return apply_filters( 'wpinv_user_info', $user_info, $this->get_id(), $this );
710
711
    }
712
713
    /**
714
	 * Get the customer id.
715
	 *
716
	 * @since 1.0.19
717
	 * @param  string $context View or edit context.
718
	 * @return int
719
	 */
720
	public function get_author( $context = 'view' ) {
721
		return (int) $this->get_prop( 'author', $context );
722
    }
723
724
    /**
725
	 * Alias of self::get_author().
726
	 *
727
	 * @since 1.0.19
728
	 * @param  string $context View or edit context.
729
	 * @return int
730
	 */
731
	public function get_user_id( $context = 'view' ) {
732
		return $this->get_author( $context );
733
    }
734
735
     /**
736
	 * Alias of self::get_author().
737
	 *
738
	 * @since 1.0.19
739
	 * @param  string $context View or edit context.
740
	 * @return int
741
	 */
742
	public function get_customer_id( $context = 'view' ) {
743
		return $this->get_author( $context );
744
    }
745
746
    /**
747
	 * Get the customer's ip.
748
	 *
749
	 * @since 1.0.19
750
	 * @param  string $context View or edit context.
751
	 * @return string
752
	 */
753
	public function get_ip( $context = 'view' ) {
754
		return $this->get_prop( 'user_ip', $context );
755
    }
756
757
    /**
758
	 * Alias of self::get_ip().
759
	 *
760
	 * @since 1.0.19
761
	 * @param  string $context View or edit context.
762
	 * @return string
763
	 */
764
	public function get_user_ip( $context = 'view' ) {
765
		return $this->get_ip( $context );
766
    }
767
768
     /**
769
	 * Alias of self::get_ip().
770
	 *
771
	 * @since 1.0.19
772
	 * @param  string $context View or edit context.
773
	 * @return string
774
	 */
775
	public function get_customer_ip( $context = 'view' ) {
776
		return $this->get_ip( $context );
777
    }
778
779
    /**
780
	 * Get the customer's first name.
781
	 *
782
	 * @since 1.0.19
783
	 * @param  string $context View or edit context.
784
	 * @return string
785
	 */
786
	public function get_first_name( $context = 'view' ) {
787
		return $this->get_prop( 'first_name', $context );
788
    }
789
790
    /**
791
	 * Alias of self::get_first_name().
792
	 *
793
	 * @since 1.0.19
794
	 * @param  string $context View or edit context.
795
	 * @return int
796
	 */
797
	public function get_user_first_name( $context = 'view' ) {
798
		return $this->get_first_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_first_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
799
    }
800
801
     /**
802
	 * Alias of self::get_first_name().
803
	 *
804
	 * @since 1.0.19
805
	 * @param  string $context View or edit context.
806
	 * @return int
807
	 */
808
	public function get_customer_first_name( $context = 'view' ) {
809
		return $this->get_first_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_first_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
810
    }
811
812
    /**
813
	 * Get the customer's last name.
814
	 *
815
	 * @since 1.0.19
816
	 * @param  string $context View or edit context.
817
	 * @return string
818
	 */
819
	public function get_last_name( $context = 'view' ) {
820
		return $this->get_prop( 'last_name', $context );
821
    }
822
823
    /**
824
	 * Alias of self::get_last_name().
825
	 *
826
	 * @since 1.0.19
827
	 * @param  string $context View or edit context.
828
	 * @return int
829
	 */
830
	public function get_user_last_name( $context = 'view' ) {
831
		return $this->get_last_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_last_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
832
    }
833
834
    /**
835
	 * Alias of self::get_last_name().
836
	 *
837
	 * @since 1.0.19
838
	 * @param  string $context View or edit context.
839
	 * @return int
840
	 */
841
	public function get_customer_last_name( $context = 'view' ) {
842
		return $this->get_last_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_last_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
843
    }
844
845
    /**
846
	 * Get the customer's full name.
847
	 *
848
	 * @since 1.0.19
849
	 * @param  string $context View or edit context.
850
	 * @return string
851
	 */
852
	public function get_full_name( $context = 'view' ) {
853
		return trim( $this->get_first_name( $context ) . ' ' . $this->get_last_name( $context ) );
854
    }
855
856
    /**
857
	 * Alias of self::get_full_name().
858
	 *
859
	 * @since 1.0.19
860
	 * @param  string $context View or edit context.
861
	 * @return int
862
	 */
863
	public function get_user_full_name( $context = 'view' ) {
864
		return $this->get_full_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_full_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
865
    }
866
867
    /**
868
	 * Alias of self::get_full_name().
869
	 *
870
	 * @since 1.0.19
871
	 * @param  string $context View or edit context.
872
	 * @return int
873
	 */
874
	public function get_customer_full_name( $context = 'view' ) {
875
		return $this->get_full_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_full_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
876
    }
877
878
    /**
879
	 * Get the customer's phone number.
880
	 *
881
	 * @since 1.0.19
882
	 * @param  string $context View or edit context.
883
	 * @return string
884
	 */
885
	public function get_phone( $context = 'view' ) {
886
		return $this->get_prop( 'phone', $context );
887
    }
888
889
    /**
890
	 * Alias of self::get_phone().
891
	 *
892
	 * @since 1.0.19
893
	 * @param  string $context View or edit context.
894
	 * @return int
895
	 */
896
	public function get_phone_number( $context = 'view' ) {
897
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
898
    }
899
900
    /**
901
	 * Alias of self::get_phone().
902
	 *
903
	 * @since 1.0.19
904
	 * @param  string $context View or edit context.
905
	 * @return int
906
	 */
907
	public function get_user_phone( $context = 'view' ) {
908
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
909
    }
910
911
    /**
912
	 * Alias of self::get_phone().
913
	 *
914
	 * @since 1.0.19
915
	 * @param  string $context View or edit context.
916
	 * @return int
917
	 */
918
	public function get_customer_phone( $context = 'view' ) {
919
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
920
    }
921
922
    /**
923
	 * Get the customer's email address.
924
	 *
925
	 * @since 1.0.19
926
	 * @param  string $context View or edit context.
927
	 * @return string
928
	 */
929
	public function get_email( $context = 'view' ) {
930
		return $this->get_prop( 'email', $context );
931
    }
932
933
    /**
934
	 * Alias of self::get_email().
935
	 *
936
	 * @since 1.0.19
937
	 * @param  string $context View or edit context.
938
	 * @return string
939
	 */
940
	public function get_email_address( $context = 'view' ) {
941
		return $this->get_email( $context );
942
    }
943
944
    /**
945
	 * Alias of self::get_email().
946
	 *
947
	 * @since 1.0.19
948
	 * @param  string $context View or edit context.
949
	 * @return int
950
	 */
951
	public function get_user_email( $context = 'view' ) {
952
		return $this->get_email( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_email($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
953
    }
954
955
    /**
956
	 * Alias of self::get_email().
957
	 *
958
	 * @since 1.0.19
959
	 * @param  string $context View or edit context.
960
	 * @return int
961
	 */
962
	public function get_customer_email( $context = 'view' ) {
963
		return $this->get_email( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_email($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
964
    }
965
966
    /**
967
	 * Get the customer's country.
968
	 *
969
	 * @since 1.0.19
970
	 * @param  string $context View or edit context.
971
	 * @return string
972
	 */
973
	public function get_country( $context = 'view' ) {
974
		$country = $this->get_prop( 'country', $context );
975
		return empty( $country ) ? wpinv_get_default_country() : $country;
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($country) ?...lt_country() : $country also could return the type array which is incompatible with the documented return type string.
Loading history...
976
    }
977
978
    /**
979
	 * Alias of self::get_country().
980
	 *
981
	 * @since 1.0.19
982
	 * @param  string $context View or edit context.
983
	 * @return int
984
	 */
985
	public function get_user_country( $context = 'view' ) {
986
		return $this->get_country( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_country($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
987
    }
988
989
    /**
990
	 * Alias of self::get_country().
991
	 *
992
	 * @since 1.0.19
993
	 * @param  string $context View or edit context.
994
	 * @return int
995
	 */
996
	public function get_customer_country( $context = 'view' ) {
997
		return $this->get_country( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_country($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
998
    }
999
1000
    /**
1001
	 * Get the customer's state.
1002
	 *
1003
	 * @since 1.0.19
1004
	 * @param  string $context View or edit context.
1005
	 * @return string
1006
	 */
1007
	public function get_state( $context = 'view' ) {
1008
		$state = $this->get_prop( 'state', $context );
1009
		return empty( $state ) ? wpinv_get_default_state() : $state;
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($state) ? w...efault_state() : $state also could return the type array which is incompatible with the documented return type string.
Loading history...
1010
    }
1011
1012
    /**
1013
	 * Alias of self::get_state().
1014
	 *
1015
	 * @since 1.0.19
1016
	 * @param  string $context View or edit context.
1017
	 * @return int
1018
	 */
1019
	public function get_user_state( $context = 'view' ) {
1020
		return $this->get_state( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_state($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
1021
    }
1022
1023
    /**
1024
	 * Alias of self::get_state().
1025
	 *
1026
	 * @since 1.0.19
1027
	 * @param  string $context View or edit context.
1028
	 * @return int
1029
	 */
1030
	public function get_customer_state( $context = 'view' ) {
1031
		return $this->get_state( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_state($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
1032
    }
1033
1034
    /**
1035
	 * Get the customer's city.
1036
	 *
1037
	 * @since 1.0.19
1038
	 * @param  string $context View or edit context.
1039
	 * @return string
1040
	 */
1041
	public function get_city( $context = 'view' ) {
1042
		return $this->get_prop( 'city', $context );
1043
    }
1044
1045
    /**
1046
	 * Alias of self::get_city().
1047
	 *
1048
	 * @since 1.0.19
1049
	 * @param  string $context View or edit context.
1050
	 * @return string
1051
	 */
1052
	public function get_user_city( $context = 'view' ) {
1053
		return $this->get_city( $context );
1054
    }
1055
1056
    /**
1057
	 * Alias of self::get_city().
1058
	 *
1059
	 * @since 1.0.19
1060
	 * @param  string $context View or edit context.
1061
	 * @return string
1062
	 */
1063
	public function get_customer_city( $context = 'view' ) {
1064
		return $this->get_city( $context );
1065
    }
1066
1067
    /**
1068
	 * Get the customer's zip.
1069
	 *
1070
	 * @since 1.0.19
1071
	 * @param  string $context View or edit context.
1072
	 * @return string
1073
	 */
1074
	public function get_zip( $context = 'view' ) {
1075
		return $this->get_prop( 'zip', $context );
1076
    }
1077
1078
    /**
1079
	 * Alias of self::get_zip().
1080
	 *
1081
	 * @since 1.0.19
1082
	 * @param  string $context View or edit context.
1083
	 * @return string
1084
	 */
1085
	public function get_user_zip( $context = 'view' ) {
1086
		return $this->get_zip( $context );
1087
    }
1088
1089
    /**
1090
	 * Alias of self::get_zip().
1091
	 *
1092
	 * @since 1.0.19
1093
	 * @param  string $context View or edit context.
1094
	 * @return string
1095
	 */
1096
	public function get_customer_zip( $context = 'view' ) {
1097
		return $this->get_zip( $context );
1098
    }
1099
1100
    /**
1101
	 * Get the customer's company.
1102
	 *
1103
	 * @since 1.0.19
1104
	 * @param  string $context View or edit context.
1105
	 * @return string
1106
	 */
1107
	public function get_company( $context = 'view' ) {
1108
		return $this->get_prop( 'company', $context );
1109
    }
1110
1111
    /**
1112
	 * Alias of self::get_company().
1113
	 *
1114
	 * @since 1.0.19
1115
	 * @param  string $context View or edit context.
1116
	 * @return string
1117
	 */
1118
	public function get_user_company( $context = 'view' ) {
1119
		return $this->get_company( $context );
1120
    }
1121
1122
    /**
1123
	 * Alias of self::get_company().
1124
	 *
1125
	 * @since 1.0.19
1126
	 * @param  string $context View or edit context.
1127
	 * @return string
1128
	 */
1129
	public function get_customer_company( $context = 'view' ) {
1130
		return $this->get_company( $context );
1131
    }
1132
1133
    /**
1134
	 * Get the customer's vat number.
1135
	 *
1136
	 * @since 1.0.19
1137
	 * @param  string $context View or edit context.
1138
	 * @return string
1139
	 */
1140
	public function get_vat_number( $context = 'view' ) {
1141
		return $this->get_prop( 'vat_number', $context );
1142
    }
1143
1144
    /**
1145
	 * Alias of self::get_vat_number().
1146
	 *
1147
	 * @since 1.0.19
1148
	 * @param  string $context View or edit context.
1149
	 * @return string
1150
	 */
1151
	public function get_user_vat_number( $context = 'view' ) {
1152
		return $this->get_vat_number( $context );
1153
    }
1154
1155
    /**
1156
	 * Alias of self::get_vat_number().
1157
	 *
1158
	 * @since 1.0.19
1159
	 * @param  string $context View or edit context.
1160
	 * @return string
1161
	 */
1162
	public function get_customer_vat_number( $context = 'view' ) {
1163
		return $this->get_vat_number( $context );
1164
    }
1165
1166
    /**
1167
	 * Get the customer's vat rate.
1168
	 *
1169
	 * @since 1.0.19
1170
	 * @param  string $context View or edit context.
1171
	 * @return string
1172
	 */
1173
	public function get_vat_rate( $context = 'view' ) {
1174
		return $this->get_prop( 'vat_rate', $context );
1175
    }
1176
1177
    /**
1178
	 * Alias of self::get_vat_rate().
1179
	 *
1180
	 * @since 1.0.19
1181
	 * @param  string $context View or edit context.
1182
	 * @return string
1183
	 */
1184
	public function get_user_vat_rate( $context = 'view' ) {
1185
		return $this->get_vat_rate( $context );
1186
    }
1187
1188
    /**
1189
	 * Alias of self::get_vat_rate().
1190
	 *
1191
	 * @since 1.0.19
1192
	 * @param  string $context View or edit context.
1193
	 * @return string
1194
	 */
1195
	public function get_customer_vat_rate( $context = 'view' ) {
1196
		return $this->get_vat_rate( $context );
1197
    }
1198
1199
    /**
1200
	 * Get the customer's address.
1201
	 *
1202
	 * @since 1.0.19
1203
	 * @param  string $context View or edit context.
1204
	 * @return string
1205
	 */
1206
	public function get_address( $context = 'view' ) {
1207
		return $this->get_prop( 'address', $context );
1208
    }
1209
1210
    /**
1211
	 * Alias of self::get_address().
1212
	 *
1213
	 * @since 1.0.19
1214
	 * @param  string $context View or edit context.
1215
	 * @return string
1216
	 */
1217
	public function get_user_address( $context = 'view' ) {
1218
		return $this->get_address( $context );
1219
    }
1220
1221
    /**
1222
	 * Alias of self::get_address().
1223
	 *
1224
	 * @since 1.0.19
1225
	 * @param  string $context View or edit context.
1226
	 * @return string
1227
	 */
1228
	public function get_customer_address( $context = 'view' ) {
1229
		return $this->get_address( $context );
1230
    }
1231
1232
    /**
1233
	 * Get whether the customer has viewed the invoice or not.
1234
	 *
1235
	 * @since 1.0.19
1236
	 * @param  string $context View or edit context.
1237
	 * @return bool
1238
	 */
1239
	public function get_is_viewed( $context = 'view' ) {
1240
		return (bool) $this->get_prop( 'is_viewed', $context );
1241
	}
1242
1243
	/**
1244
	 * Get other recipients for invoice communications.
1245
	 *
1246
	 * @since 1.0.19
1247
	 * @param  string $context View or edit context.
1248
	 * @return bool
1249
	 */
1250
	public function get_email_cc( $context = 'view' ) {
1251
		return $this->get_prop( 'email_cc', $context );
1252
	}
1253
1254
	/**
1255
	 * Get invoice template.
1256
	 *
1257
	 * @since 1.0.19
1258
	 * @param  string $context View or edit context.
1259
	 * @return bool
1260
	 */
1261
	public function get_template( $context = 'view' ) {
1262
		return $this->get_prop( 'template', $context );
1263
	}
1264
1265
	/**
1266
	 * Get whether the customer has confirmed their address.
1267
	 *
1268
	 * @since 1.0.19
1269
	 * @param  string $context View or edit context.
1270
	 * @return bool
1271
	 */
1272
	public function get_address_confirmed( $context = 'view' ) {
1273
		return (bool) $this->get_prop( 'address_confirmed', $context );
1274
    }
1275
1276
    /**
1277
	 * Alias of self::get_address_confirmed().
1278
	 *
1279
	 * @since 1.0.19
1280
	 * @param  string $context View or edit context.
1281
	 * @return bool
1282
	 */
1283
	public function get_user_address_confirmed( $context = 'view' ) {
1284
		return $this->get_address_confirmed( $context );
1285
    }
1286
1287
    /**
1288
	 * Alias of self::get_address().
1289
	 *
1290
	 * @since 1.0.19
1291
	 * @param  string $context View or edit context.
1292
	 * @return bool
1293
	 */
1294
	public function get_customer_address_confirmed( $context = 'view' ) {
1295
		return $this->get_address_confirmed( $context );
1296
    }
1297
1298
    /**
1299
	 * Get the invoice subtotal.
1300
	 *
1301
	 * @since 1.0.19
1302
	 * @param  string $context View or edit context.
1303
	 * @return float
1304
	 */
1305
	public function get_subtotal( $context = 'view' ) {
1306
        $subtotal = (float) $this->get_prop( 'subtotal', $context );
1307
1308
        // Backwards compatibility.
1309
        if ( is_bool( $context ) && $context ) {
0 ignored issues
show
introduced by
The condition is_bool($context) is always false.
Loading history...
1310
            return wpinv_price( wpinv_format_amount( $subtotal ), $this->get_currency() );
1311
        }
1312
1313
        return $subtotal;
1314
    }
1315
1316
    /**
1317
	 * Get the invoice discount total.
1318
	 *
1319
	 * @since 1.0.19
1320
	 * @param  string $context View or edit context.
1321
	 * @return float
1322
	 */
1323
	public function get_total_discount( $context = 'view' ) {
1324
		return (float) $this->get_prop( 'total_discount', $context );
1325
    }
1326
1327
    /**
1328
	 * Get the invoice tax total.
1329
	 *
1330
	 * @since 1.0.19
1331
	 * @param  string $context View or edit context.
1332
	 * @return float
1333
	 */
1334
	public function get_total_tax( $context = 'view' ) {
1335
		return (float) $this->get_prop( 'total_tax', $context );
1336
	}
1337
1338
	/**
1339
	 * @deprecated
1340
	 */
1341
	public function get_final_tax( $currency = false ) {
1342
		$tax = $this->get_total_tax();
1343
1344
        if ( $currency ) {
1345
			return wpinv_price( wpinv_format_amount( $tax, NULL, false ), $this->get_currency() );
1346
        }
1347
1348
        return $tax;
1349
    }
1350
1351
    /**
1352
	 * Get the invoice fees total.
1353
	 *
1354
	 * @since 1.0.19
1355
	 * @param  string $context View or edit context.
1356
	 * @return float
1357
	 */
1358
	public function get_total_fees( $context = 'view' ) {
1359
		return (float) $this->get_prop( 'total_fees', $context );
1360
    }
1361
1362
    /**
1363
	 * Alias for self::get_total_fees().
1364
	 *
1365
	 * @since 1.0.19
1366
	 * @param  string $context View or edit context.
1367
	 * @return float
1368
	 */
1369
	public function get_fees_total( $context = 'view' ) {
1370
		return $this->get_total_fees( $context );
1371
    }
1372
1373
    /**
1374
	 * Get the invoice total.
1375
	 *
1376
	 * @since 1.0.19
1377
     * @return float
1378
	 */
1379
	public function get_total() {
1380
		$total = $this->is_renewal() ? $this->get_recurring_total() : $this->get_initial_total();
1381
		return apply_filters( 'getpaid_get_invoice_total_amount', $total, $this  );
1382
	}
1383
	
1384
	/**
1385
	 * Get the invoice totals.
1386
	 *
1387
	 * @since 1.0.19
1388
     * @return float
1389
	 */
1390
	public function get_totals() {
1391
		return $this->totals;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->totals returns the type array which is incompatible with the documented return type double.
Loading history...
1392
    }
1393
1394
    /**
1395
	 * Get the initial invoice total.
1396
	 *
1397
	 * @since 1.0.19
1398
     * @param  string $context View or edit context.
1399
     * @return float
1400
	 */
1401
    public function get_initial_total() {
1402
1403
		if ( empty( $this->totals ) ) {
1404
			$this->recalculate_total();
1405
		}
1406
1407
		$tax      = $this->totals['tax']['initial'];
1408
		$fee      = $this->totals['fee']['initial'];
1409
		$discount = $this->totals['discount']['initial'];
1410
		$subtotal = $this->totals['subtotal']['initial'];
1411
		$total    = $tax + $fee - $discount + $subtotal;
1412
1413
		if ( 0 > $total ) {
1414
			$total = 0;
1415
		}
1416
1417
        return apply_filters( 'wpinv_get_initial_invoice_total', $total, $this );
1418
	}
1419
1420
	/**
1421
	 * Get the recurring invoice total.
1422
	 *
1423
	 * @since 1.0.19
1424
     * @param  string $context View or edit context.
1425
     * @return float
1426
	 */
1427
    public function get_recurring_total() {
1428
1429
		if ( empty( $this->totals ) ) {
1430
			$this->recalculate_total();
1431
		}
1432
1433
		$tax      = $this->totals['tax']['recurring'];
1434
		$fee      = $this->totals['fee']['recurring'];
1435
		$discount = $this->totals['discount']['recurring'];
1436
		$subtotal = $this->totals['subtotal']['recurring'];
1437
		$total    = $tax + $fee - $discount + $subtotal;
1438
1439
		if ( 0 > $total ) {
1440
			$total = 0;
1441
		}
1442
1443
        return apply_filters( 'wpinv_get_recurring_invoice_total', $total, $this );
1444
	}
1445
1446
	/**
1447
	 * Returns recurring payment details.
1448
	 *
1449
	 * @since 1.0.19
1450
     * @param  string $field Optionally provide a field to return.
1451
	 * @param string $currency Whether to include the currency.
1452
     * @return float
1453
	 */
1454
    public function get_recurring_details( $field = '', $currency = false ) {
1455
1456
		// Maybe recalculate totals.
1457
		if ( empty( $this->totals ) ) {
1458
			$this->recalculate_total();
1459
		}
1460
1461
		// Prepare recurring totals.
1462
        $data = apply_filters(
1463
			'wpinv_get_invoice_recurring_details',
1464
			array(
1465
				'cart_details' => $this->get_cart_details(),
1466
				'subtotal'     => $this->totals['subtotal']['recurring'],
1467
				'discount'     => $this->totals['discount']['recurring'],
1468
				'tax'          => $this->totals['tax']['recurring'],
1469
				'fee'          => $this->totals['fee']['recurring'],
1470
				'total'        => $this->get_recurring_total(),
1471
			),
1472
			$this,
1473
			$field,
1474
			$currency
1475
		);
1476
1477
        if ( isset( $data[$field] ) ) {
1478
            return ( $currency ? wpinv_price( $data[$field], $this->get_currency() ) : $data[$field] );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $currency ? wpinv...ency()) : $data[$field] also could return the type string which is incompatible with the documented return type double.
Loading history...
1479
        }
1480
1481
        return $data;
1482
    }
1483
1484
    /**
1485
	 * Get the invoice fees.
1486
	 *
1487
	 * @since 1.0.19
1488
	 * @param  string $context View or edit context.
1489
	 * @return array
1490
	 */
1491
	public function get_fees( $context = 'view' ) {
1492
		return wpinv_parse_list( $this->get_prop( 'fees', $context ) );
1493
    }
1494
1495
    /**
1496
	 * Get the invoice discounts.
1497
	 *
1498
	 * @since 1.0.19
1499
	 * @param  string $context View or edit context.
1500
	 * @return array
1501
	 */
1502
	public function get_discounts( $context = 'view' ) {
1503
		return wpinv_parse_list( $this->get_prop( 'discounts', $context ) );
1504
    }
1505
1506
    /**
1507
	 * Get the invoice taxes.
1508
	 *
1509
	 * @since 1.0.19
1510
	 * @param  string $context View or edit context.
1511
	 * @return array
1512
	 */
1513
	public function get_taxes( $context = 'view' ) {
1514
		return wpinv_parse_list( $this->get_prop( 'taxes', $context ) );
1515
    }
1516
1517
    /**
1518
	 * Get the invoice items.
1519
	 *
1520
	 * @since 1.0.19
1521
	 * @param  string $context View or edit context.
1522
	 * @return GetPaid_Form_Item[]
1523
	 */
1524
	public function get_items( $context = 'view' ) {
1525
        return $this->get_prop( 'items', $context );
1526
    }
1527
1528
    /**
1529
	 * Get the invoice's payment form.
1530
	 *
1531
	 * @since 1.0.19
1532
	 * @param  string $context View or edit context.
1533
	 * @return int
1534
	 */
1535
	public function get_payment_form( $context = 'view' ) {
1536
		return intval( $this->get_prop( 'payment_form', $context ) );
1537
    }
1538
1539
    /**
1540
	 * Get the invoice's submission id.
1541
	 *
1542
	 * @since 1.0.19
1543
	 * @param  string $context View or edit context.
1544
	 * @return string
1545
	 */
1546
	public function get_submission_id( $context = 'view' ) {
1547
		return $this->get_prop( 'submission_id', $context );
1548
    }
1549
1550
    /**
1551
	 * Get the invoice's discount code.
1552
	 *
1553
	 * @since 1.0.19
1554
	 * @param  string $context View or edit context.
1555
	 * @return string
1556
	 */
1557
	public function get_discount_code( $context = 'view' ) {
1558
		return $this->get_prop( 'discount_code', $context );
1559
    }
1560
1561
    /**
1562
	 * Get the invoice's gateway.
1563
	 *
1564
	 * @since 1.0.19
1565
	 * @param  string $context View or edit context.
1566
	 * @return string
1567
	 */
1568
	public function get_gateway( $context = 'view' ) {
1569
		return $this->get_prop( 'gateway', $context );
1570
    }
1571
1572
    /**
1573
	 * Get the invoice's gateway display title.
1574
	 *
1575
	 * @since 1.0.19
1576
	 * @return string
1577
	 */
1578
    public function get_gateway_title() {
1579
        $title =  wpinv_get_gateway_checkout_label( $this->get_gateway() );
1580
        return apply_filters( 'wpinv_gateway_title', $title, $this->get_id(), $this );
1581
    }
1582
1583
    /**
1584
	 * Get the invoice's transaction id.
1585
	 *
1586
	 * @since 1.0.19
1587
	 * @param  string $context View or edit context.
1588
	 * @return string
1589
	 */
1590
	public function get_transaction_id( $context = 'view' ) {
1591
		return $this->get_prop( 'transaction_id', $context );
1592
    }
1593
1594
    /**
1595
	 * Get the invoice's currency.
1596
	 *
1597
	 * @since 1.0.19
1598
	 * @param  string $context View or edit context.
1599
	 * @return string
1600
	 */
1601
	public function get_currency( $context = 'view' ) {
1602
        $currency = $this->get_prop( 'currency', $context );
1603
        return empty( $currency ) ? wpinv_get_currency() : $currency;
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($currency) ..._currency() : $currency also could return the type array which is incompatible with the documented return type string.
Loading history...
1604
    }
1605
1606
    /**
1607
	 * Checks if we are charging taxes for this invoice.
1608
	 *
1609
	 * @since 1.0.19
1610
	 * @param  string $context View or edit context.
1611
	 * @return bool
1612
	 */
1613
	public function get_disable_taxes( $context = 'view' ) {
1614
        return (bool) $this->get_prop( 'disable_taxes', $context );
1615
    }
1616
1617
    /**
1618
	 * Retrieves the subscription id for an invoice.
1619
	 *
1620
	 * @since 1.0.19
1621
	 * @param  string $context View or edit context.
1622
	 * @return int
1623
	 */
1624
    public function get_subscription_id( $context = 'view' ) {
1625
		return $this->is_renewal() ? $this->get_parent()->get_subscription_id( $context ) : $this->get_subscription_id( $context );
1626
	}
1627
1628
	/**
1629
	 * Retrieves the remote subscription id for an invoice.
1630
	 *
1631
	 * @since 1.0.19
1632
	 * @param  string $context View or edit context.
1633
	 * @return int
1634
	 */
1635
    public function get_remote_subscription_id( $context = 'view' ) {
1636
        $subscription_id = $this->get_prop( 'remote_subscription_id', $context );
1637
1638
        if ( empty( $subscription_id ) && $this->is_renewal() ) {
1639
            $parent = $this->get_parent();
1640
            return $parent->get_subscription_id( $context );
1641
        }
1642
1643
        return $subscription_id;
1644
    }
1645
1646
    /**
1647
	 * Retrieves the payment meta for an invoice.
1648
	 *
1649
	 * @since 1.0.19
1650
	 * @param  string $context View or edit context.
1651
	 * @return array
1652
	 */
1653
    public function get_payment_meta( $context = 'view' ) {
1654
1655
        return array(
1656
            'price'        => $this->get_total( $context ),
0 ignored issues
show
Unused Code introduced by
The call to WPInv_Invoice::get_total() has too many arguments starting with $context. ( Ignorable by Annotation )

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

1656
            'price'        => $this->/** @scrutinizer ignore-call */ get_total( $context ),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1657
            'date'         => $this->get_date_created( $context ),
1658
            'user_email'   => $this->get_email( $context ),
1659
            'invoice_key'  => $this->get_key( $context ),
1660
            'currency'     => $this->get_currency( $context ),
1661
            'items'        => $this->get_items( $context ),
1662
            'user_info'    => $this->get_user_info( $context ),
1663
            'cart_details' => $this->get_cart_details(),
1664
            'status'       => $this->get_status( $context ),
1665
            'fees'         => $this->get_fees( $context ),
1666
            'taxes'        => $this->get_taxes( $context ),
1667
        );
1668
1669
    }
1670
1671
    /**
1672
	 * Retrieves the cart details for an invoice.
1673
	 *
1674
	 * @since 1.0.19
1675
	 * @return array
1676
	 */
1677
    public function get_cart_details() {
1678
        $items        = $this->get_items();
1679
        $cart_details = array();
1680
1681
        foreach ( $items as $item_id => $item ) {
1682
            $cart_details[] = $item->prepare_data_for_saving();
1683
        }
1684
1685
        return $cart_details;
1686
	}
1687
1688
	/**
1689
	 * Retrieves the recurring item.
1690
	 *
1691
	 * @return null|GetPaid_Form_Item|int
1692
	 */
1693
	public function get_recurring( $object = false ) {
1694
1695
		// Are we returning an object?
1696
        if ( $object ) {
1697
            return $this->get_item( $this->recurring_item );
1698
        }
1699
1700
        return $this->recurring_item;
1701
    }
1702
1703
	/**
1704
	 * Retrieves the subscription name.
1705
	 *
1706
	 * @since 1.0.19
1707
	 * @return string
1708
	 */
1709
	public function get_subscription_name() {
1710
1711
		// Retrieve the recurring name
1712
        $item = $this->get_recurring( true );
1713
1714
		// Abort if it does not exist.
1715
        if ( empty( $item ) ) {
1716
            return '';
1717
        }
1718
1719
		// Return the item name.
1720
        return apply_filters( 'wpinv_invoice_get_subscription_name', $item->get_name(), $this );
1721
	}
1722
1723
	/**
1724
	 * Retrieves the view url.
1725
	 *
1726
	 * @since 1.0.19
1727
	 * @return string
1728
	 */
1729
	public function get_view_url() {
1730
        $invoice_url = get_permalink( $this->get_id() );
1731
		$invoice_url = add_query_arg( 'invoice_key', $this->get_key(), $invoice_url );
1732
        return apply_filters( 'wpinv_get_view_url', $invoice_url, $this );
1733
	}
1734
1735
	/**
1736
	 * Retrieves the payment url.
1737
	 *
1738
	 * @since 1.0.19
1739
	 * @return string
1740
	 */
1741
	public function get_checkout_payment_url( $deprecated = false, $secret = false ) {
1742
1743
		// Retrieve the checkout url.
1744
        $pay_url = wpinv_get_checkout_uri();
1745
1746
		// Maybe force ssl.
1747
        if ( is_ssl() ) {
1748
            $pay_url = str_replace( 'http:', 'https:', $pay_url );
1749
        }
1750
1751
		// Add the invoice key.
1752
		$pay_url = add_query_arg( 'invoice_key', $this->get_key(), $pay_url );
1753
1754
		// (Maybe?) add a secret
1755
        if ( $secret ) {
1756
            $pay_url = add_query_arg( array( '_wpipay' => md5( $this->get_user_id() . '::' . $this->get_email() . '::' . $this->get_key() ) ), $pay_url );
1757
        }
1758
1759
        return apply_filters( 'wpinv_get_checkout_payment_url', $pay_url, $this, $deprecated, $secret );
1760
	}
1761
	
1762
	/**
1763
	 * Retrieves the receipt url.
1764
	 *
1765
	 * @since 1.0.19
1766
	 * @return string
1767
	 */
1768
	public function get_receipt_url() {
1769
1770
		// Retrieve the checkout url.
1771
        $receipt_url = wpinv_get_success_page_uri();
1772
1773
		// Maybe force ssl.
1774
        if ( is_ssl() ) {
1775
            $receipt_url = str_replace( 'http:', 'https:', $receipt_url );
1776
        }
1777
1778
		// Add the invoice key.
1779
		$receipt_url = add_query_arg( 'invoice_key', $this->get_key(), $receipt_url );
1780
1781
        return apply_filters( 'getpaid_get_invoice_receipt_url', $receipt_url, $this );
1782
    }
1783
1784
    /**
1785
	 * Magic method for accessing invoice properties.
1786
	 *
1787
	 * @since 1.0.15
1788
	 * @access public
1789
	 *
1790
	 * @param string $key Discount data to retrieve
1791
	 * @param  string $context View or edit context.
1792
	 * @return mixed Value of the given invoice property (if set).
1793
	 */
1794
	public function get( $key, $context = 'view' ) {
1795
        return $this->get_prop( $key, $context );
1796
	}
1797
1798
    /*
1799
	|--------------------------------------------------------------------------
1800
	| Setters
1801
	|--------------------------------------------------------------------------
1802
	|
1803
	| Functions for setting item data. These should not update anything in the
1804
	| database itself and should only change what is stored in the class
1805
	| object.
1806
    */
1807
1808
    /**
1809
	 * Magic method for setting invoice properties.
1810
	 *
1811
	 * @since 1.0.19
1812
	 * @access public
1813
	 *
1814
	 * @param string $key Discount data to retrieve
1815
	 * @param  mixed $value new value.
1816
	 * @return mixed Value of the given invoice property (if set).
1817
	 */
1818
	public function set( $key, $value ) {
1819
1820
        $setter = "set_$key";
1821
        if ( is_callable( array( $this, $setter ) ) ) {
1822
            $this->{$setter}( $value );
1823
        }
1824
1825
	}
1826
1827
	/**
1828
	 * Sets item status.
1829
	 *
1830
	 * @since 1.0.19
1831
	 * @param string $new_status    New status.
1832
	 * @param string $note          Optional note to add.
1833
	 * @param bool   $manual_update Is this a manual status change?.
1834
	 * @return array details of change.
1835
	 */
1836
	public function set_status( $new_status, $note = '', $manual_update = false ) {
1837
		$old_status = $this->get_status();
1838
1839
		$statuses = $this->get_all_statuses();
1840
1841
		if ( isset( $statuses[ 'draft' ] ) ) {
1842
			unset( $statuses[ 'draft' ] );
1843
		}
1844
1845
		$this->set_prop( 'status', $new_status );
1846
1847
		// If setting the status, ensure it's set to a valid status.
1848
		if ( true === $this->object_read ) {
1849
1850
			// Only allow valid new status.
1851
			if ( ! array_key_exists( $new_status, $statuses ) ) {
1852
				$new_status = 'wpi-pending';
1853
			}
1854
1855
			// If the old status is set but unknown (e.g. draft) assume its pending for action usage.
1856
			if ( $old_status && ! array_key_exists( $new_status, $statuses ) ) {
1857
				$old_status = 'wpi-pending';
1858
			}
1859
1860
			// Paid - Renewal (i.e when duplicating a parent invoice )
1861
			if ( $new_status == 'wpi-pending' && $old_status == 'publish' && ! $this->get_id() ) {
1862
				$old_status = 'wpi-pending';
1863
			}
1864
1865
		}
1866
1867
		if ( true === $this->object_read && $old_status !== $new_status ) {
1868
			$this->status_transition = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('from' => ! empty(...> (bool)$manual_update) of type array<string,boolean|mixed|string> is incompatible with the declared type boolean of property $status_transition.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1869
				'from'   => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $old_status,
1870
				'to'     => $new_status,
1871
				'note'   => $note,
1872
				'manual' => (bool) $manual_update,
1873
			);
1874
1875
			if ( $manual_update ) {
1876
				do_action( 'getpaid_' . $this->object_type .'_edit_status', $this->get_id(), $new_status );
1877
			}
1878
1879
			$this->maybe_set_date_paid();
1880
1881
		}
1882
1883
		return array(
1884
			'from' => $old_status,
1885
			'to'   => $new_status,
1886
		);
1887
	}
1888
1889
	/**
1890
	 * Maybe set date paid.
1891
	 *
1892
	 * Sets the date paid variable when transitioning to the payment complete
1893
	 * order status.
1894
	 *
1895
	 * @since 1.0.19
1896
	 */
1897
	public function maybe_set_date_paid() {
1898
1899
		if ( ! $this->get_date_completed( 'edit' ) && $this->is_paid() ) {
1900
			$this->set_date_completed( current_time( 'mysql' ) );
1901
		}
1902
	}
1903
1904
    /**
1905
	 * Set parent invoice ID.
1906
	 *
1907
	 * @since 1.0.19
1908
	 */
1909
	public function set_parent_id( $value ) {
1910
		if ( $value && ( $value === $this->get_id() ) ) {
1911
			return;
1912
		}
1913
		$this->set_prop( 'parent_id', absint( $value ) );
1914
    }
1915
1916
    /**
1917
	 * Set plugin version when the invoice was created.
1918
	 *
1919
	 * @since 1.0.19
1920
	 */
1921
	public function set_version( $value ) {
1922
		$this->set_prop( 'version', $value );
1923
    }
1924
1925
    /**
1926
	 * Set date when the invoice was created.
1927
	 *
1928
	 * @since 1.0.19
1929
	 * @param string $value Value to set.
1930
     * @return bool Whether or not the date was set.
1931
	 */
1932
	public function set_date_created( $value ) {
1933
        $date = strtotime( $value );
1934
1935
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
1936
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
1937
            return true;
1938
        }
1939
1940
        return $this->set_prop( 'date_created', '' );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('date_created', '') targeting GetPaid_Data::set_prop() 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...
1941
1942
    }
1943
1944
    /**
1945
	 * Set date invoice due date.
1946
	 *
1947
	 * @since 1.0.19
1948
	 * @param string $value Value to set.
1949
     * @return bool Whether or not the date was set.
1950
	 */
1951
	public function set_due_date( $value ) {
1952
        $date = strtotime( $value );
1953
1954
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
1955
            $this->set_prop( 'due_date', date( 'Y-m-d H:i:s', $date ) );
1956
            return true;
1957
        }
1958
1959
		$this->set_prop( 'due_date', '' );
1960
        return false;
1961
1962
    }
1963
1964
    /**
1965
	 * Alias of self::set_due_date().
1966
	 *
1967
	 * @since 1.0.19
1968
	 * @param  string $value New name.
1969
	 */
1970
	public function set_date_due( $value ) {
1971
		$this->set_due_date( $value );
1972
    }
1973
1974
    /**
1975
	 * Set date invoice was completed.
1976
	 *
1977
	 * @since 1.0.19
1978
	 * @param string $value Value to set.
1979
     * @return bool Whether or not the date was set.
1980
	 */
1981
	public function set_completed_date( $value ) {
1982
        $date = strtotime( $value );
1983
1984
        if ( $date && $value !== '0000-00-00 00:00:00'  ) {
1985
            $this->set_prop( 'completed_date', date( 'Y-m-d H:i:s', $date ) );
1986
            return true;
1987
        }
1988
1989
		$this->set_prop( 'completed_date', '' );
1990
        return false;
1991
1992
    }
1993
1994
    /**
1995
	 * Alias of self::set_completed_date().
1996
	 *
1997
	 * @since 1.0.19
1998
	 * @param  string $value New name.
1999
	 */
2000
	public function set_date_completed( $value ) {
2001
		$this->set_completed_date( $value );
2002
    }
2003
2004
    /**
2005
	 * Set date when the invoice was last modified.
2006
	 *
2007
	 * @since 1.0.19
2008
	 * @param string $value Value to set.
2009
     * @return bool Whether or not the date was set.
2010
	 */
2011
	public function set_date_modified( $value ) {
2012
        $date = strtotime( $value );
2013
2014
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
2015
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
2016
            return true;
2017
        }
2018
2019
		$this->set_prop( 'date_modified', '' );
2020
        return false;
2021
2022
    }
2023
2024
    /**
2025
	 * Set the invoice number.
2026
	 *
2027
	 * @since 1.0.19
2028
	 * @param  string $value New number.
2029
	 */
2030
	public function set_number( $value ) {
2031
        $number = sanitize_text_field( $value );
2032
		$this->set_prop( 'number', $number );
2033
    }
2034
2035
    /**
2036
	 * Set the invoice type.
2037
	 *
2038
	 * @since 1.0.19
2039
	 * @param  string $value Type.
2040
	 */
2041
	public function set_type( $value ) {
2042
        $type = sanitize_text_field( str_replace( 'wpi_', '', $value ) );
2043
		$this->set_prop( 'type', $type );
2044
	}
2045
2046
    /**
2047
	 * Set the invoice post type.
2048
	 *
2049
	 * @since 1.0.19
2050
	 * @param  string $value Post type.
2051
	 */
2052
	public function set_post_type( $value ) {
2053
        if ( getpaid_is_invoice_post_type( $value ) ) {
2054
			$this->set_type( $value );
2055
            $this->set_prop( 'post_type', $value );
2056
        }
2057
    }
2058
2059
    /**
2060
	 * Set the invoice key.
2061
	 *
2062
	 * @since 1.0.19
2063
	 * @param  string $value New key.
2064
	 */
2065
	public function set_key( $value ) {
2066
        $key = sanitize_text_field( $value );
2067
		$this->set_prop( 'key', $key );
2068
    }
2069
2070
    /**
2071
	 * Set the invoice mode.
2072
	 *
2073
	 * @since 1.0.19
2074
	 * @param  string $value mode.
2075
	 */
2076
	public function set_mode( $value ) {
2077
        if ( ! in_array( $value, array( 'live', 'test' ) ) ) {
2078
            $this->set_prop( 'value', $value );
2079
        }
2080
    }
2081
2082
    /**
2083
	 * Set the invoice path.
2084
	 *
2085
	 * @since 1.0.19
2086
	 * @param  string $value path.
2087
	 */
2088
	public function set_path( $value ) {
2089
        $this->set_prop( 'path', $value );
2090
    }
2091
2092
    /**
2093
	 * Set the invoice name.
2094
	 *
2095
	 * @since 1.0.19
2096
	 * @param  string $value New name.
2097
	 */
2098
	public function set_name( $value ) {
2099
        $name = sanitize_text_field( $value );
2100
		$this->set_prop( 'name', $name );
2101
    }
2102
2103
    /**
2104
	 * Alias of self::set_name().
2105
	 *
2106
	 * @since 1.0.19
2107
	 * @param  string $value New name.
2108
	 */
2109
	public function set_title( $value ) {
2110
		$this->set_name( $value );
2111
    }
2112
2113
    /**
2114
	 * Set the invoice description.
2115
	 *
2116
	 * @since 1.0.19
2117
	 * @param  string $value New description.
2118
	 */
2119
	public function set_description( $value ) {
2120
        $description = wp_kses_post( $value );
2121
		return $this->set_prop( 'description', $description );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('description', $description) targeting GetPaid_Data::set_prop() 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...
2122
    }
2123
2124
    /**
2125
	 * Alias of self::set_description().
2126
	 *
2127
	 * @since 1.0.19
2128
	 * @param  string $value New description.
2129
	 */
2130
	public function set_excerpt( $value ) {
2131
		$this->set_description( $value );
2132
    }
2133
2134
    /**
2135
	 * Alias of self::set_description().
2136
	 *
2137
	 * @since 1.0.19
2138
	 * @param  string $value New description.
2139
	 */
2140
	public function set_summary( $value ) {
2141
		$this->set_description( $value );
2142
    }
2143
2144
    /**
2145
	 * Set the receiver of the invoice.
2146
	 *
2147
	 * @since 1.0.19
2148
	 * @param  int $value New author.
2149
	 */
2150
	public function set_author( $value ) {
2151
		$user = get_user_by( 'id', (int) $value );
2152
2153
		if ( $user && $user->ID ) {
2154
			$this->set_prop( 'author', $user->ID );
2155
			$this->set_prop( 'email', $user->user_email );
2156
		}
2157
		
2158
    }
2159
2160
    /**
2161
	 * Alias of self::set_author().
2162
	 *
2163
	 * @since 1.0.19
2164
	 * @param  int $value New user id.
2165
	 */
2166
	public function set_user_id( $value ) {
2167
		$this->set_author( $value );
2168
    }
2169
2170
    /**
2171
	 * Alias of self::set_author().
2172
	 *
2173
	 * @since 1.0.19
2174
	 * @param  int $value New user id.
2175
	 */
2176
	public function set_customer_id( $value ) {
2177
		$this->set_author( $value );
2178
    }
2179
2180
    /**
2181
	 * Set the customer's ip.
2182
	 *
2183
	 * @since 1.0.19
2184
	 * @param  string $value ip address.
2185
	 */
2186
	public function set_ip( $value ) {
2187
		$this->set_prop( 'ip', $value );
2188
    }
2189
2190
    /**
2191
	 * Alias of self::set_ip().
2192
	 *
2193
	 * @since 1.0.19
2194
	 * @param  string $value ip address.
2195
	 */
2196
	public function set_user_ip( $value ) {
2197
		$this->set_ip( $value );
2198
    }
2199
2200
    /**
2201
	 * Set the customer's first name.
2202
	 *
2203
	 * @since 1.0.19
2204
	 * @param  string $value first name.
2205
	 */
2206
	public function set_first_name( $value ) {
2207
		$this->set_prop( 'first_name', $value );
2208
    }
2209
2210
    /**
2211
	 * Alias of self::set_first_name().
2212
	 *
2213
	 * @since 1.0.19
2214
	 * @param  string $value first name.
2215
	 */
2216
	public function set_user_first_name( $value ) {
2217
		$this->set_first_name( $value );
2218
    }
2219
2220
    /**
2221
	 * Alias of self::set_first_name().
2222
	 *
2223
	 * @since 1.0.19
2224
	 * @param  string $value first name.
2225
	 */
2226
	public function set_customer_first_name( $value ) {
2227
		$this->set_first_name( $value );
2228
    }
2229
2230
    /**
2231
	 * Set the customer's last name.
2232
	 *
2233
	 * @since 1.0.19
2234
	 * @param  string $value last name.
2235
	 */
2236
	public function set_last_name( $value ) {
2237
		$this->set_prop( 'last_name', $value );
2238
    }
2239
2240
    /**
2241
	 * Alias of self::set_last_name().
2242
	 *
2243
	 * @since 1.0.19
2244
	 * @param  string $value last name.
2245
	 */
2246
	public function set_user_last_name( $value ) {
2247
		$this->set_last_name( $value );
2248
    }
2249
2250
    /**
2251
	 * Alias of self::set_last_name().
2252
	 *
2253
	 * @since 1.0.19
2254
	 * @param  string $value last name.
2255
	 */
2256
	public function set_customer_last_name( $value ) {
2257
		$this->set_last_name( $value );
2258
    }
2259
2260
    /**
2261
	 * Set the customer's phone number.
2262
	 *
2263
	 * @since 1.0.19
2264
	 * @param  string $value phone.
2265
	 */
2266
	public function set_phone( $value ) {
2267
		$this->set_prop( 'phone', $value );
2268
    }
2269
2270
    /**
2271
	 * Alias of self::set_phone().
2272
	 *
2273
	 * @since 1.0.19
2274
	 * @param  string $value phone.
2275
	 */
2276
	public function set_user_phone( $value ) {
2277
		$this->set_phone( $value );
2278
    }
2279
2280
    /**
2281
	 * Alias of self::set_phone().
2282
	 *
2283
	 * @since 1.0.19
2284
	 * @param  string $value phone.
2285
	 */
2286
	public function set_customer_phone( $value ) {
2287
		$this->set_phone( $value );
2288
    }
2289
2290
    /**
2291
	 * Alias of self::set_phone().
2292
	 *
2293
	 * @since 1.0.19
2294
	 * @param  string $value phone.
2295
	 */
2296
	public function set_phone_number( $value ) {
2297
		$this->set_phone( $value );
2298
    }
2299
2300
    /**
2301
	 * Set the customer's email address.
2302
	 *
2303
	 * @since 1.0.19
2304
	 * @param  string $value email address.
2305
	 */
2306
	public function set_email( $value ) {
2307
		$this->set_prop( 'email', $value );
2308
    }
2309
2310
    /**
2311
	 * Alias of self::set_email().
2312
	 *
2313
	 * @since 1.0.19
2314
	 * @param  string $value email address.
2315
	 */
2316
	public function set_user_email( $value ) {
2317
		$this->set_email( $value );
2318
    }
2319
2320
    /**
2321
	 * Alias of self::set_email().
2322
	 *
2323
	 * @since 1.0.19
2324
	 * @param  string $value email address.
2325
	 */
2326
	public function set_email_address( $value ) {
2327
		$this->set_email( $value );
2328
    }
2329
2330
    /**
2331
	 * Alias of self::set_email().
2332
	 *
2333
	 * @since 1.0.19
2334
	 * @param  string $value email address.
2335
	 */
2336
	public function set_customer_email( $value ) {
2337
		$this->set_email( $value );
2338
    }
2339
2340
    /**
2341
	 * Set the customer's country.
2342
	 *
2343
	 * @since 1.0.19
2344
	 * @param  string $value country.
2345
	 */
2346
	public function set_country( $value ) {
2347
		$this->set_prop( 'country', $value );
2348
    }
2349
2350
    /**
2351
	 * Alias of self::set_country().
2352
	 *
2353
	 * @since 1.0.19
2354
	 * @param  string $value country.
2355
	 */
2356
	public function set_user_country( $value ) {
2357
		$this->set_country( $value );
2358
    }
2359
2360
    /**
2361
	 * Alias of self::set_country().
2362
	 *
2363
	 * @since 1.0.19
2364
	 * @param  string $value country.
2365
	 */
2366
	public function set_customer_country( $value ) {
2367
		$this->set_country( $value );
2368
    }
2369
2370
    /**
2371
	 * Set the customer's state.
2372
	 *
2373
	 * @since 1.0.19
2374
	 * @param  string $value state.
2375
	 */
2376
	public function set_state( $value ) {
2377
		$this->set_prop( 'state', $value );
2378
    }
2379
2380
    /**
2381
	 * Alias of self::set_state().
2382
	 *
2383
	 * @since 1.0.19
2384
	 * @param  string $value state.
2385
	 */
2386
	public function set_user_state( $value ) {
2387
		$this->set_state( $value );
2388
    }
2389
2390
    /**
2391
	 * Alias of self::set_state().
2392
	 *
2393
	 * @since 1.0.19
2394
	 * @param  string $value state.
2395
	 */
2396
	public function set_customer_state( $value ) {
2397
		$this->set_state( $value );
2398
    }
2399
2400
    /**
2401
	 * Set the customer's city.
2402
	 *
2403
	 * @since 1.0.19
2404
	 * @param  string $value city.
2405
	 */
2406
	public function set_city( $value ) {
2407
		$this->set_prop( 'city', $value );
2408
    }
2409
2410
    /**
2411
	 * Alias of self::set_city().
2412
	 *
2413
	 * @since 1.0.19
2414
	 * @param  string $value city.
2415
	 */
2416
	public function set_user_city( $value ) {
2417
		$this->set_city( $value );
2418
    }
2419
2420
    /**
2421
	 * Alias of self::set_city().
2422
	 *
2423
	 * @since 1.0.19
2424
	 * @param  string $value city.
2425
	 */
2426
	public function set_customer_city( $value ) {
2427
		$this->set_city( $value );
2428
    }
2429
2430
    /**
2431
	 * Set the customer's zip code.
2432
	 *
2433
	 * @since 1.0.19
2434
	 * @param  string $value zip.
2435
	 */
2436
	public function set_zip( $value ) {
2437
		$this->set_prop( 'zip', $value );
2438
    }
2439
2440
    /**
2441
	 * Alias of self::set_zip().
2442
	 *
2443
	 * @since 1.0.19
2444
	 * @param  string $value zip.
2445
	 */
2446
	public function set_user_zip( $value ) {
2447
		$this->set_zip( $value );
2448
    }
2449
2450
    /**
2451
	 * Alias of self::set_zip().
2452
	 *
2453
	 * @since 1.0.19
2454
	 * @param  string $value zip.
2455
	 */
2456
	public function set_customer_zip( $value ) {
2457
		$this->set_zip( $value );
2458
    }
2459
2460
    /**
2461
	 * Set the customer's company.
2462
	 *
2463
	 * @since 1.0.19
2464
	 * @param  string $value company.
2465
	 */
2466
	public function set_company( $value ) {
2467
		$this->set_prop( 'company', $value );
2468
    }
2469
2470
    /**
2471
	 * Alias of self::set_company().
2472
	 *
2473
	 * @since 1.0.19
2474
	 * @param  string $value company.
2475
	 */
2476
	public function set_user_company( $value ) {
2477
		$this->set_company( $value );
2478
    }
2479
2480
    /**
2481
	 * Alias of self::set_company().
2482
	 *
2483
	 * @since 1.0.19
2484
	 * @param  string $value company.
2485
	 */
2486
	public function set_customer_company( $value ) {
2487
		$this->set_company( $value );
2488
    }
2489
2490
    /**
2491
	 * Set the customer's var number.
2492
	 *
2493
	 * @since 1.0.19
2494
	 * @param  string $value var number.
2495
	 */
2496
	public function set_vat_number( $value ) {
2497
		$this->set_prop( 'vat_number', $value );
2498
    }
2499
2500
    /**
2501
	 * Alias of self::set_vat_number().
2502
	 *
2503
	 * @since 1.0.19
2504
	 * @param  string $value var number.
2505
	 */
2506
	public function set_user_vat_number( $value ) {
2507
		$this->set_vat_number( $value );
2508
    }
2509
2510
    /**
2511
	 * Alias of self::set_vat_number().
2512
	 *
2513
	 * @since 1.0.19
2514
	 * @param  string $value var number.
2515
	 */
2516
	public function set_customer_vat_number( $value ) {
2517
		$this->set_vat_number( $value );
2518
    }
2519
2520
    /**
2521
	 * Set the customer's vat rate.
2522
	 *
2523
	 * @since 1.0.19
2524
	 * @param  string $value var rate.
2525
	 */
2526
	public function set_vat_rate( $value ) {
2527
		$this->set_prop( 'vat_rate', $value );
2528
    }
2529
2530
    /**
2531
	 * Alias of self::set_vat_rate().
2532
	 *
2533
	 * @since 1.0.19
2534
	 * @param  string $value var number.
2535
	 */
2536
	public function set_user_vat_rate( $value ) {
2537
		$this->set_vat_rate( $value );
2538
    }
2539
2540
    /**
2541
	 * Alias of self::set_vat_rate().
2542
	 *
2543
	 * @since 1.0.19
2544
	 * @param  string $value var number.
2545
	 */
2546
	public function set_customer_vat_rate( $value ) {
2547
		$this->set_vat_rate( $value );
2548
    }
2549
2550
    /**
2551
	 * Set the customer's address.
2552
	 *
2553
	 * @since 1.0.19
2554
	 * @param  string $value address.
2555
	 */
2556
	public function set_address( $value ) {
2557
		$this->set_prop( 'address', $value );
2558
    }
2559
2560
    /**
2561
	 * Alias of self::set_address().
2562
	 *
2563
	 * @since 1.0.19
2564
	 * @param  string $value address.
2565
	 */
2566
	public function set_user_address( $value ) {
2567
		$this->set_address( $value );
2568
    }
2569
2570
    /**
2571
	 * Alias of self::set_address().
2572
	 *
2573
	 * @since 1.0.19
2574
	 * @param  string $value address.
2575
	 */
2576
	public function set_customer_address( $value ) {
2577
		$this->set_address( $value );
2578
    }
2579
2580
    /**
2581
	 * Set whether the customer has viewed the invoice or not.
2582
	 *
2583
	 * @since 1.0.19
2584
	 * @param  int|bool $value confirmed.
2585
	 */
2586
	public function set_is_viewed( $value ) {
2587
		$this->set_prop( 'is_viewed', $value );
2588
	}
2589
2590
	/**
2591
	 * Set extra email recipients.
2592
	 *
2593
	 * @since 1.0.19
2594
	 * @param  string $value email recipients.
2595
	 */
2596
	public function set_email_cc( $value ) {
2597
		$this->set_prop( 'email_cc', $value );
2598
	}
2599
2600
	/**
2601
	 * Set the invoice template.
2602
	 *
2603
	 * @since 1.0.19
2604
	 * @param  string $value email recipients.
2605
	 */
2606
	public function set_template( $value ) {
2607
		if ( in_array( $value, array( 'quantity', 'hours', 'amount' ) ) ) {
2608
			$this->set_prop( 'template', $value );
2609
		}
2610
	}
2611
2612
	/**
2613
	 * Set the customer's address confirmed status.
2614
	 *
2615
	 * @since 1.0.19
2616
	 * @param  int|bool $value confirmed.
2617
	 */
2618
	public function set_address_confirmed( $value ) {
2619
		$this->set_prop( 'address_confirmed', $value );
2620
    }
2621
2622
    /**
2623
	 * Alias of self::set_address_confirmed().
2624
	 *
2625
	 * @since 1.0.19
2626
	 * @param  int|bool $value confirmed.
2627
	 */
2628
	public function set_user_address_confirmed( $value ) {
2629
		$this->set_address_confirmed( $value );
2630
    }
2631
2632
    /**
2633
	 * Alias of self::set_address_confirmed().
2634
	 *
2635
	 * @since 1.0.19
2636
	 * @param  int|bool $value confirmed.
2637
	 */
2638
	public function set_customer_address_confirmed( $value ) {
2639
		$this->set_address_confirmed( $value );
2640
    }
2641
2642
    /**
2643
	 * Set the invoice sub total.
2644
	 *
2645
	 * @since 1.0.19
2646
	 * @param  float $value sub total.
2647
	 */
2648
	public function set_subtotal( $value ) {
2649
		$this->set_prop( 'subtotal', $value );
2650
    }
2651
2652
    /**
2653
	 * Set the invoice discount amount.
2654
	 *
2655
	 * @since 1.0.19
2656
	 * @param  float $value discount total.
2657
	 */
2658
	public function set_total_discount( $value ) {
2659
		$this->set_prop( 'total_discount', $value );
2660
    }
2661
2662
    /**
2663
	 * Alias of self::set_total_discount().
2664
	 *
2665
	 * @since 1.0.19
2666
	 * @param  float $value discount total.
2667
	 */
2668
	public function set_discount( $value ) {
2669
		$this->set_total_discount( $value );
2670
    }
2671
2672
    /**
2673
	 * Set the invoice tax amount.
2674
	 *
2675
	 * @since 1.0.19
2676
	 * @param  float $value tax total.
2677
	 */
2678
	public function set_total_tax( $value ) {
2679
		$this->set_prop( 'total_tax', $value );
2680
    }
2681
2682
    /**
2683
	 * Alias of self::set_total_tax().
2684
	 *
2685
	 * @since 1.0.19
2686
	 * @param  float $value tax total.
2687
	 */
2688
	public function set_tax_total( $value ) {
2689
		$this->set_total_tax( $value );
2690
    }
2691
2692
    /**
2693
	 * Set the invoice fees amount.
2694
	 *
2695
	 * @since 1.0.19
2696
	 * @param  float $value fees total.
2697
	 */
2698
	public function set_total_fees( $value ) {
2699
		$this->set_prop( 'total_fees', $value );
2700
    }
2701
2702
    /**
2703
	 * Alias of self::set_total_fees().
2704
	 *
2705
	 * @since 1.0.19
2706
	 * @param  float $value fees total.
2707
	 */
2708
	public function set_fees_total( $value ) {
2709
		$this->set_total_fees( $value );
2710
    }
2711
2712
    /**
2713
	 * Set the invoice fees.
2714
	 *
2715
	 * @since 1.0.19
2716
	 * @param  array $value fees.
2717
	 */
2718
	public function set_fees( $value ) {
2719
2720
        $this->set_prop( 'fees', array() );
2721
2722
        // Ensure that we have an array.
2723
        if ( ! is_array( $value ) ) {
0 ignored issues
show
introduced by
The condition is_array($value) is always true.
Loading history...
2724
            return;
2725
        }
2726
2727
        foreach ( $value as $name => $data ) {
2728
            if ( isset( $data['amount'] ) ) {
2729
                $this->add_fee( $name, $data['amount'], $data['recurring'] );
2730
            }
2731
        }
2732
2733
    }
2734
2735
    /**
2736
	 * Set the invoice taxes.
2737
	 *
2738
	 * @since 1.0.19
2739
	 * @param  array $value taxes.
2740
	 */
2741
	public function set_taxes( $value ) {
2742
		$this->set_prop( 'taxes', $value );
2743
    }
2744
2745
    /**
2746
	 * Set the invoice discounts.
2747
	 *
2748
	 * @since 1.0.19
2749
	 * @param  array $value discounts.
2750
	 */
2751
	public function set_discounts( $value ) {
2752
		$this->set_prop( 'discounts', array() );
2753
2754
        // Ensure that we have an array.
2755
        if ( ! is_array( $value ) ) {
0 ignored issues
show
introduced by
The condition is_array($value) is always true.
Loading history...
2756
            return;
2757
        }
2758
2759
        foreach ( $value as $name => $data ) {
2760
            if ( isset( $data['amount'] ) ) {
2761
                $this->add_discount( $name, $data['amount'], $data['recurring'] );
2762
            }
2763
        }
2764
    }
2765
2766
    /**
2767
	 * Set the invoice items.
2768
	 *
2769
	 * @since 1.0.19
2770
	 * @param  GetPaid_Form_Item[] $value items.
2771
	 */
2772
	public function set_items( $value ) {
2773
2774
        // Remove existing items.
2775
        $this->set_prop( 'items', array() );
2776
2777
        // Ensure that we have an array.
2778
        if ( ! is_array( $value ) ) {
0 ignored issues
show
introduced by
The condition is_array($value) is always true.
Loading history...
2779
            return;
2780
        }
2781
2782
        foreach ( $value as $item ) {
2783
            $this->add_item( $item );
2784
        }
2785
2786
    }
2787
2788
    /**
2789
	 * Set the payment form.
2790
	 *
2791
	 * @since 1.0.19
2792
	 * @param  int $value payment form.
2793
	 */
2794
	public function set_payment_form( $value ) {
2795
		$this->set_prop( 'payment_form', $value );
2796
    }
2797
2798
    /**
2799
	 * Set the submission id.
2800
	 *
2801
	 * @since 1.0.19
2802
	 * @param  string $value submission id.
2803
	 */
2804
	public function set_submission_id( $value ) {
2805
		$this->set_prop( 'submission_id', $value );
2806
    }
2807
2808
    /**
2809
	 * Set the discount code.
2810
	 *
2811
	 * @since 1.0.19
2812
	 * @param  string $value discount code.
2813
	 */
2814
	public function set_discount_code( $value ) {
2815
		$this->set_prop( 'discount_code', $value );
2816
    }
2817
2818
    /**
2819
	 * Set the gateway.
2820
	 *
2821
	 * @since 1.0.19
2822
	 * @param  string $value gateway.
2823
	 */
2824
	public function set_gateway( $value ) {
2825
		$this->set_prop( 'gateway', $value );
2826
    }
2827
2828
    /**
2829
	 * Set the transaction id.
2830
	 *
2831
	 * @since 1.0.19
2832
	 * @param  string $value transaction id.
2833
	 */
2834
	public function set_transaction_id( $value ) {
2835
		if ( ! empty( $value ) ) {
2836
			$this->set_prop( 'transaction_id', $value );
2837
		}
2838
    }
2839
2840
    /**
2841
	 * Set the currency id.
2842
	 *
2843
	 * @since 1.0.19
2844
	 * @param  string $value currency id.
2845
	 */
2846
	public function set_currency( $value ) {
2847
		$this->set_prop( 'currency', $value );
2848
    }
2849
2850
	/**
2851
	 * Set whether to disable taxes.
2852
	 *
2853
	 * @since 1.0.19
2854
	 * @param  bool $value value.
2855
	 */
2856
	public function set_disable_taxes( $value ) {
2857
		$this->set_prop( 'disable_taxes', (bool) $value );
2858
	}
2859
2860
    /**
2861
	 * Set the subscription id.
2862
	 *
2863
	 * @since 1.0.19
2864
	 * @param  string $value subscription id.
2865
	 */
2866
	public function set_subscription_id( $value ) {
2867
		$this->set_prop( 'subscription_id', $value );
2868
	}
2869
	
2870
	/**
2871
	 * Set the remote subscription id.
2872
	 *
2873
	 * @since 1.0.19
2874
	 * @param  string $value subscription id.
2875
	 */
2876
	public function set_remote_subscription_id( $value ) {
2877
		$this->set_prop( 'remote_subscription_id', $value );
2878
    }
2879
2880
    /*
2881
	|--------------------------------------------------------------------------
2882
	| Boolean methods
2883
	|--------------------------------------------------------------------------
2884
	|
2885
	| Return true or false.
2886
	|
2887
    */
2888
2889
    /**
2890
     * Checks if this is a parent invoice.
2891
     */
2892
    public function is_parent() {
2893
        $parent = $this->get_parent_id();
2894
        return apply_filters( 'wpinv_invoice_is_parent', empty( $parent ), $this );
2895
    }
2896
2897
    /**
2898
     * Checks if this is a renewal invoice.
2899
     */
2900
    public function is_renewal() {
2901
        return ! $this->is_parent();
2902
    }
2903
2904
    /**
2905
     * Checks if this is a recurring invoice.
2906
     */
2907
    public function is_recurring() {
2908
        return $this->is_renewal() || ! empty( $this->recurring_item );
2909
    }
2910
2911
    /**
2912
     * Checks if this is a taxable invoice.
2913
     */
2914
    public function is_taxable() {
2915
        return ! $this->get_disable_taxes();
2916
	}
2917
2918
	/**
2919
	 * @deprecated
2920
	 */
2921
	public function has_vat() {
2922
        global $wpinv_euvat, $wpi_country;
2923
2924
        $requires_vat = false;
2925
2926
        if ( $this->country ) {
0 ignored issues
show
Bug Best Practice introduced by
The property country does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
2927
            $wpi_country        = $this->country;
2928
            $requires_vat       = $wpinv_euvat->requires_vat( $requires_vat, $this->get_user_id(), $wpinv_euvat->invoice_has_digital_rule( $this ) );
2929
        }
2930
2931
        return apply_filters( 'wpinv_invoice_has_vat', $requires_vat, $this );
2932
	}
2933
2934
	/**
2935
	 * Checks to see if the invoice requires payment.
2936
	 */
2937
	public function is_free() {
2938
        $is_free = ( (float) wpinv_round_amount( $this->get_initial_total() ) == 0 );
2939
2940
		if ( $this->is_recurring() && $this->get_recurring_total() > 0 ) {
2941
			$is_free = false;
2942
		}
2943
2944
        return apply_filters( 'wpinv_invoice_is_free', $is_free, $this );
2945
    }
2946
2947
    /**
2948
     * Checks if the invoice is paid.
2949
     */
2950
    public function is_paid() {
2951
        $is_paid = $this->has_status( array( 'publish', 'wpi-processing', 'wpi-renewal' ) );
2952
        return apply_filters( 'wpinv_invoice_is_paid', $is_paid, $this );
2953
	}
2954
2955
	/**
2956
     * Checks if the invoice needs payment.
2957
     */
2958
	public function needs_payment() {
2959
		$needs_payment = ! $this->is_paid() && ! $this->is_refunded() && ! $this->is_free();
2960
        return apply_filters( 'wpinv_needs_payment', $needs_payment, $this );
2961
    }
2962
2963
	/**
2964
     * Checks if the invoice is refunded.
2965
     */
2966
	public function is_refunded() {
2967
        $is_refunded = $this->has_status( 'wpi-refunded' );
2968
        return apply_filters( 'wpinv_invoice_is_refunded', $is_refunded, $this );
2969
	}
2970
2971
	/**
2972
     * Checks if the invoice is held.
2973
     */
2974
	public function is_held() {
2975
        $is_held = $this->has_status( 'wpi-onhold' );
2976
        return apply_filters( 'wpinv_invoice_is_held', $is_held, $this );
2977
	}
2978
2979
	/**
2980
     * Checks if the invoice is due.
2981
     */
2982
	public function is_due() {
2983
		$due_date = $this->get_due_date();
2984
		return empty( $due_date ) ? false : current_time( 'timestamp' ) > strtotime( $due_date );
2985
	}
2986
2987
	/**
2988
     * Checks if the invoice is draft.
2989
     */
2990
	public function is_draft() {
2991
        return $this->has_status( 'draft, auto-draft' );
2992
	}
2993
2994
    /**
2995
     * Checks if the invoice has a given status.
2996
     */
2997
    public function has_status( $status ) {
2998
        $status = wpinv_parse_list( $status );
2999
        return apply_filters( 'wpinv_has_status', in_array( $this->get_status(), $status ), $status );
3000
	}
3001
3002
	/**
3003
     * Checks if the invoice is of a given type.
3004
     */
3005
    public function is_type( $type ) {
3006
        $type = wpinv_parse_list( $type );
3007
        return in_array( $this->get_type(), $type );
3008
    }
3009
3010
    /**
3011
     * Checks if this is a quote object.
3012
     *
3013
     * @since 1.0.15
3014
     */
3015
    public function is_quote() {
3016
        return 'wpi_quote' == $this->get_post_type();
3017
    }
3018
3019
    /**
3020
     * Check if the invoice (or it's parent has a free trial).
3021
     *
3022
     */
3023
    public function has_free_trial() {
3024
        return $this->is_recurring() && 0 == $this->get_initial_total();
3025
	}
3026
3027
	/**
3028
     * @deprecated
3029
     */
3030
    public function is_free_trial() {
3031
        $this->has_free_trial();
3032
    }
3033
3034
	/**
3035
     * Check if the initial payment if 0.
3036
     *
3037
     */
3038
	public function is_initial_free() {
3039
        $is_initial_free = ! ( (float) wpinv_round_amount( $this->get_initial_total() ) > 0 );
3040
        return apply_filters( 'wpinv_invoice_is_initial_free', $is_initial_free, $this->get_cart_details(), $this );
3041
    }
3042
	
3043
	/**
3044
     * Check if the recurring item has a free trial.
3045
     *
3046
     */
3047
    public function item_has_free_trial() {
3048
3049
        // Ensure we have a recurring item.
3050
        if ( ! $this->is_recurring() ) {
3051
            return false;
3052
        }
3053
3054
        $item = $this->get_recurring( true );
3055
        return $item->has_free_trial();
3056
	}
3057
3058
	/**
3059
     * Check if the free trial is a result of a discount.
3060
     */
3061
    public function is_free_trial_from_discount() {
3062
		return $this->has_free_trial() && ! $this->item_has_free_trial();
3063
	}
3064
	
3065
	/**
3066
     * @deprecated
3067
     */
3068
    public function discount_first_payment_only() {
3069
3070
		$discount_code = $this->get_discount_code();
3071
        if ( empty( $this->discount_code ) || ! $this->is_recurring() ) {
0 ignored issues
show
Bug Best Practice introduced by
The property discount_code does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
3072
            return true;
3073
        }
3074
3075
        $discount = wpinv_get_discount_obj( $discount_code );
3076
3077
        if ( ! $discount || ! $discount->exists() ) {
0 ignored issues
show
introduced by
$discount is of type WPInv_Discount, thus it always evaluated to true.
Loading history...
3078
            return true;
3079
        }
3080
3081
        return ! $discount->get_is_recurring();
3082
    }
3083
3084
    /*
3085
	|--------------------------------------------------------------------------
3086
	| Cart related methods
3087
	|--------------------------------------------------------------------------
3088
	|
3089
	| Do not forget to recalculate totals after calling the following methods.
3090
	|
3091
    */
3092
3093
    /**
3094
     * Adds an item to the invoice.
3095
     *
3096
     * @param GetPaid_Form_Item|array $item
3097
     * @return WP_Error|Bool
3098
     */
3099
    public function add_item( $item ) {
3100
3101
		if ( is_array( $item ) ) {
3102
			$item = $this->process_array_item( $item );
3103
		}
3104
3105
		if ( is_numeric( $item ) ) {
0 ignored issues
show
introduced by
The condition is_numeric($item) is always false.
Loading history...
3106
			$item = new GetPaid_Form_Item( $item );
3107
		}
3108
3109
        // Make sure that it is available for purchase.
3110
		if ( $item->get_id() > 0 && ! $item->can_purchase() ) {
3111
			return new WP_Error( 'invalid_item', __( 'This item is not available for purchase', 'invoicing' ) );
3112
        }
3113
3114
        // Do we have a recurring item?
3115
		if ( $item->is_recurring() ) {
3116
3117
			// An invoice can only contain one recurring item.
3118
			if ( ! empty( $this->recurring_item  && $this->recurring_item != (int) $item->get_id() ) ) {
3119
				return new WP_Error( 'recurring_item', __( 'An invoice can only contain one recurring item', 'invoicing' ) );
3120
			}
3121
3122
			$this->recurring_item = $item->get_id();
3123
        }
3124
3125
        // Invoice id.
3126
        $item->invoice_id = (int) $this->get_id();
3127
3128
        // Retrieve all items.
3129
        $items = $this->get_items();
3130
        $items[ (int) $item->get_id() ] = $item;
3131
3132
        $this->set_prop( 'items', $items );
3133
		return true;
3134
	}
3135
	
3136
	/**
3137
	 * Converts an array to an item.
3138
	 *
3139
	 * @since 1.0.19
3140
	 * @return GetPaid_Form_Item
3141
	 */
3142
	protected function process_array_item( $array ) {
3143
3144
		$item_id = isset( $array['item_id'] ) ? $array['item_id'] : 0;
3145
		$item    = new GetPaid_Form_Item( $item_id );
3146
3147
		// Set item data.
3148
		foreach( array( 'name', 'price', 'description' ) as $key ) {
3149
			if ( isset( $array[ "item_$key" ] ) ) {
3150
				$method = "set_$key";
3151
				$item->$method( $array[ "item_$key" ] );
3152
			}
3153
		}
3154
3155
		if ( isset( $array['quantity'] ) ) {
3156
			$item->set_quantity( $array['quantity'] );
3157
		}
3158
3159
		// Set item meta.
3160
		if ( isset( $array['meta'] ) && is_array( $array['meta'] ) ) {
3161
			$item->set_item_meta( $array['meta'] );
3162
		}
3163
3164
		return $item;
3165
3166
	}
3167
3168
    /**
3169
	 * Retrieves a specific item.
3170
	 *
3171
	 * @since 1.0.19
3172
	 */
3173
	public function get_item( $item_id ) {
3174
		$items   = $this->get_items();
3175
		$item_id = (int) $item_id;
3176
		return ( ! empty( $item_id ) && isset( $items[ $item_id ] ) ) ? $items[ $item_id ] : null;
3177
    }
3178
3179
    /**
3180
	 * Removes a specific item.
3181
	 *
3182
	 * @since 1.0.19
3183
	 */
3184
	public function remove_item( $item_id ) {
3185
		$items   = $this->get_items();
3186
		$item_id = (int) $item_id;
3187
3188
        if ( $item_id == $this->recurring_item ) {
3189
            $this->recurring_item = null;
3190
        }
3191
3192
        if ( isset( $items[ $item_id ] ) ) {
3193
            unset( $items[ $item_id ] );
3194
            $this->set_prop( 'items', $items );
3195
        }
3196
    }
3197
3198
    /**
3199
     * Adds a fee to the invoice.
3200
     *
3201
     * @param string $fee
3202
     * @param float $value
3203
     * @return WP_Error|Bool
3204
     */
3205
    public function add_fee( $fee, $value, $recurring = false ) {
3206
3207
        $amount = wpinv_sanitize_amount( $value );
3208
        $fees   = $this->get_fees();
3209
3210
        if ( isset( $fees[ $fee ] ) && isset( $fees[ $fee ]['amount'] ) ) {
3211
3212
            $amount = $fees[ $fee ]['amount'] += $amount;
3213
			$fees[ $fee ] = array(
3214
				'amount'    => $amount,
3215
                'recurring' => (bool) $recurring,
3216
            );
3217
3218
		} else {
3219
			$fees[ $fee ] = array(
3220
                'amount'    => $amount,
3221
                'recurring' => (bool) $recurring,
3222
            );
3223
		}
3224
3225
        $this->set_prop( 'fees', $fee );
3226
3227
    }
3228
3229
    /**
3230
	 * Retrieves a specific fee.
3231
	 *
3232
	 * @since 1.0.19
3233
	 */
3234
	public function get_fee( $fee ) {
3235
        $fees = $this->get_fees();
3236
		return isset( $fees[ $fee ] ) ? $fees[ $fee ] : null;
3237
    }
3238
3239
    /**
3240
	 * Removes a specific fee.
3241
	 *
3242
	 * @since 1.0.19
3243
	 */
3244
	public function remove_fee( $fee ) {
3245
        $fees = $this->get_fees();
3246
        if ( isset( $fees[ $fee ] ) ) {
3247
            unset( $fees[ $fee ] );
3248
            $this->set_prop( 'fees', $fees );
3249
        }
3250
    }
3251
3252
    /**
3253
     * Adds a discount to the invoice.
3254
     *
3255
     * @param string $discount
3256
     * @param float $value
3257
     * @return WP_Error|Bool
3258
     */
3259
    public function add_discount( $discount, $value, $recurring = false ) {
3260
3261
        $amount    = wpinv_sanitize_amount( $value );
3262
        $discounts = $this->get_discounts();
3263
3264
        if ( isset( $discounts[ $discount ] ) && isset( $discounts[ $discount ]['amount'] ) ) {
3265
3266
            $amount = $discounts[ $discount ]['amount'] += $amount;
3267
			$discounts[ $discount ] = array(
3268
                'amount'    => $amount,
3269
                'recurring' => (bool) $recurring,
3270
            );
3271
3272
		} else {
3273
			$discounts[ $discount ] = array(
3274
                'amount'    => $amount,
3275
                'recurring' => (bool) $recurring,
3276
            );
3277
		}
3278
3279
        $this->set_prop( 'discounts', $discount );
3280
3281
    }
3282
3283
    /**
3284
	 * Retrieves a specific discount.
3285
	 *
3286
	 * @since 1.0.19
3287
	 */
3288
	public function get_discount( $discount = false ) {
3289
3290
		// Backwards compatibilty.
3291
		if ( empty( $discount ) ) {
3292
			return $this->get_total_discount();
3293
		}
3294
3295
        $discounts = $this->get_discounts();
3296
		return isset( $discounts[ $discount ] ) ? $discounts[ $discount ] : null;
3297
    }
3298
3299
    /**
3300
	 * Removes a specific discount.
3301
	 *
3302
	 * @since 1.0.19
3303
	 */
3304
	public function remove_discount( $discount ) {
3305
        $discounts = $this->get_discounts();
3306
        if ( isset( $discounts[ $discount ] ) ) {
3307
            unset( $discounts[ $discount ] );
3308
            $this->set_prop( 'discounts', $discounts );
3309
        }
3310
    }
3311
3312
    /**
3313
     * Adds a tax to the invoice.
3314
     *
3315
     * @param string $tax
3316
     * @param float $value
3317
     */
3318
    public function add_tax( $tax, $value, $recurring = true ) {
3319
3320
        if ( ! $this->is_taxable() ) {
3321
            return;
3322
        }
3323
3324
        $amount    = wpinv_sanitize_amount( $value );
3325
        $taxes     = $this->get_taxes();
3326
3327
        if ( isset( $taxes[ $tax ] ) && isset( $taxes[ $tax ]['amount'] ) ) {
3328
3329
            $amount = $taxes[ $tax ]['amount'] += $amount;
3330
			$taxes[ $tax ] = array(
3331
                'amount'    => $amount,
3332
                'recurring' => (bool) $recurring,
3333
            );
3334
3335
		} else {
3336
			$taxes[ $tax ] = array(
3337
                'amount'    => $amount,
3338
                'recurring' => (bool) $recurring,
3339
            );
3340
		}
3341
3342
        $this->set_prop( 'taxes', $tax );
3343
3344
    }
3345
3346
    /**
3347
	 * Retrieves a specific tax.
3348
	 *
3349
	 * @since 1.0.19
3350
	 */
3351
	public function get_tax( $tax = null ) {
3352
3353
		// Backwards compatility.
3354
		if ( empty( $tax ) ) {
3355
			return $this->get_total_tax();
3356
		}
3357
3358
        $taxes = $this->get_taxes();
3359
		return isset( $taxes[ $tax ] ) ? $taxes[ $tax ] : null;
3360
    }
3361
3362
    /**
3363
	 * Removes a specific tax.
3364
	 *
3365
	 * @since 1.0.19
3366
	 */
3367
	public function remove_tax( $tax ) {
3368
        $taxes = $this->get_discounts();
3369
        if ( isset( $taxes[ $tax ] ) ) {
3370
            unset( $taxes[ $tax ] );
3371
            $this->set_prop( 'taxes', $taxes );
3372
        }
3373
    }
3374
3375
    /**
3376
	 * Recalculates the invoice subtotal.
3377
	 *
3378
	 * @since 1.0.19
3379
	 * @return float The recalculated subtotal
3380
	 */
3381
	public function recalculate_subtotal() {
3382
        $items     = $this->get_items();
3383
		$subtotal  = 0;
3384
		$recurring = 0;
3385
3386
        foreach ( $items as $item ) {
3387
			$subtotal  += $item->get_sub_total();
3388
			$recurring += $item->get_recurring_sub_total();
3389
        }
3390
3391
		if ( $this->is_renewal() ) {
3392
			$this->set_subtotal( $recurring );
3393
		} else {
3394
			$this->set_subtotal( $subtotal );
3395
		}
3396
3397
		$this->totals['subtotal'] = array(
3398
			'initial'   => $subtotal,
3399
			'recurring' => $recurring,
3400
		);
3401
3402
        return $this->is_renewal() ? $recurring : $subtotal;
3403
    }
3404
3405
    /**
3406
	 * Recalculates the invoice discount total.
3407
	 *
3408
	 * @since 1.0.19
3409
	 * @return float The recalculated discount
3410
	 */
3411
	public function recalculate_total_discount() {
3412
        $discounts = $this->get_discounts();
3413
		$discount  = 0;
3414
		$recurring = 0;
3415
3416
        foreach ( $discounts as $data ) {
3417
3418
			if ( $data['recurring'] ) {
3419
				$recurring += $data['amount'];
3420
			} else {
3421
				$discount += $data['amount'];
3422
			}
3423
3424
		}
3425
3426
		if ( $this->is_renewal() ) {
3427
			$this->set_total_discount( $recurring );
3428
		} else {
3429
			$this->set_total_discount( $discount );
3430
		}
3431
3432
		$this->totals['discount'] = array(
3433
			'initial'   => $discount,
3434
			'recurring' => $recurring,
3435
		);
3436
3437
		return $this->is_renewal() ? $recurring : $discount;
3438
3439
    }
3440
3441
    /**
3442
	 * Recalculates the invoice tax total.
3443
	 *
3444
	 * @since 1.0.19
3445
	 * @return float The recalculated tax
3446
	 */
3447
	public function recalculate_total_tax() {
3448
        $taxes     = $this->get_taxes();
3449
		$tax       = 0;
3450
		$recurring = 0;
3451
3452
        foreach ( $taxes as $data ) {
3453
3454
			if ( $data['recurring'] ) {
3455
				$recurring += $data['amount'];
3456
			} else {
3457
				$tax += $data['amount'];
3458
			}
3459
3460
		}
3461
3462
		if ( $this->is_renewal() ) {
3463
			$this->set_total_tax( $recurring );
3464
		} else {
3465
			$this->set_total_tax( $tax );
3466
		}
3467
3468
		$this->totals['tax'] = array(
3469
			'initial'   => $tax,
3470
			'recurring' => $recurring,
3471
		);
3472
3473
		return $this->is_renewal() ? $recurring : $tax;
3474
3475
    }
3476
3477
    /**
3478
	 * Recalculates the invoice fees total.
3479
	 *
3480
	 * @since 1.0.19
3481
	 * @return float The recalculated fee
3482
	 */
3483
	public function recalculate_total_fees() {
3484
		$fees      = $this->get_fees();
3485
		$fee       = 0;
3486
		$recurring = 0;
3487
3488
        foreach ( $fees as $data ) {
3489
3490
			if ( $data['recurring'] ) {
3491
				$recurring += $data['amount'];
3492
			} else {
3493
				$fee += $data['amount'];
3494
			}
3495
3496
		}
3497
3498
        if ( $this->is_renewal() ) {
3499
			$this->set_total_fees( $recurring );
3500
		} else {
3501
			$this->set_total_fees( $fee );
3502
		}
3503
3504
		$this->totals['fee'] = array(
3505
			'initial'   => $fee,
3506
			'recurring' => $recurring,
3507
		);
3508
3509
        $this->set_total_fees( $fee );
3510
        return $this->is_renewal() ? $recurring : $fee;
3511
    }
3512
3513
    /**
3514
	 * Recalculates the invoice total.
3515
	 *
3516
	 * @since 1.0.19
3517
     * @return float The invoice total
3518
	 */
3519
	public function recalculate_total() {
3520
        $this->recalculate_subtotal();
3521
        $this->recalculate_total_fees();
3522
        $this->recalculate_total_discount();
3523
        $this->recalculate_total_tax();
3524
		return $this->get_total();
3525
	}
3526
3527
	/**
3528
	 * @deprecated
3529
	 */
3530
    public function recalculate_totals( $temp = false ) {
3531
        $this->update_items( $temp );
0 ignored issues
show
Deprecated Code introduced by
The function WPInv_Invoice::update_items() has been deprecated. ( Ignorable by Annotation )

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

3531
        /** @scrutinizer ignore-deprecated */ $this->update_items( $temp );
Loading history...
3532
        $this->save( true );
0 ignored issues
show
Unused Code introduced by
The call to WPInv_Invoice::save() has too many arguments starting with true. ( Ignorable by Annotation )

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

3532
        $this->/** @scrutinizer ignore-call */ 
3533
               save( true );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
3533
        return $this;
3534
    }
3535
3536
    /**
3537
     * Convert this to an array.
3538
     */
3539
    public function array_convert() {
3540
        return $this->get_data();
3541
    }
3542
3543
    /**
3544
     * Adds a note to an invoice.
3545
     *
3546
     * @param string $note The note being added.
3547
	 * @return int|false The new note's ID on success, false on failure.
3548
     *
3549
     */
3550
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3551
3552
        // Bail if no note specified or this invoice is not yet saved.
3553
        if ( ! $note || $this->get_id() == 0 || ( ! is_user_logged_in() && ! $system ) ) {
3554
            return false;
3555
        }
3556
3557
		// If this is an admin comment or it has been added by the user.
3558
		if ( is_user_logged_in() && ( wpinv_current_user_can_manage_invoicing() || $added_by_user ) ) {
3559
			$user         = get_user_by( 'id', get_current_user_id() );
3560
            $author       = $user->display_name;
3561
            $author_email = $user->user_email;
3562
		} 
3563
3564
		if ( $system ) {
3565
			$author       = 'System';
3566
            $author_email = '[email protected]';
3567
		}
3568
3569
		return getpaid_notes()->add_invoice_note( $this, $note, $author, $author_email, $customer_type );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $author_email does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $author does not seem to be defined for all execution paths leading up to this point.
Loading history...
3570
3571
	}
3572
3573
	/**
3574
     * Generates a unique key for the invoice.
3575
     */
3576
    public function generate_key( $string = '' ) {
3577
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3578
        return strtolower(
3579
            $string . md5( $this->get_id() . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3580
        );
3581
    }
3582
3583
    /**
3584
     * Generates a new number for the invoice.
3585
     */
3586
    public function generate_number() {
3587
        $number = $this->get_id();
3588
3589
        if ( $this->has_status( 'auto-draft' ) && wpinv_sequential_number_active( $this->post_type ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
3590
            $number = wpinv_get_next_invoice_number( $this->post_type );
3591
        }
3592
3593
		$number = wpinv_format_invoice_number( $number, $this->post_type );
3594
3595
		return $number;
3596
	}
3597
3598
	/**
3599
	 * Handle the status transition.
3600
	 */
3601
	protected function status_transition() {
3602
		$status_transition = $this->status_transition;
3603
3604
		// Reset status transition variable.
3605
		$this->status_transition = false;
3606
3607
		if ( $status_transition ) {
3608
			try {
3609
3610
				// Fire a hook for the status change.
3611
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this, $status_transition );
3612
3613
				// @deprecated this is deprecated and will be removed in the future.
3614
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3615
3616
				if ( ! empty( $status_transition['from'] ) ) {
3617
3618
					/* translators: 1: old invoice status 2: new invoice status */
3619
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'] ), wpinv_status_nicename( $status_transition['to'] ) );
3620
3621
					// Fire another hook.
3622
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this );
3623
					do_action( 'getpaid_invoice_status_changed', $this, $status_transition['from'], $status_transition['to'] );
3624
3625
					// @deprecated this is deprecated and will be removed in the future.
3626
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3627
3628
					// Note the transition occurred.
3629
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3630
3631
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3632
					if (
3633
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'wpi-pending', 'wpi-failed', 'wpi-refunded' ), true )
3634
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3635
					) {
3636
						do_action( 'getpaid_invoice_payment_status_changed', $this, $status_transition );
3637
					}
3638
				} else {
3639
					/* translators: %s: new invoice status */
3640
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'] ) );
3641
3642
					// Note the transition occurred.
3643
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3644
3645
				}
3646
			} catch ( Exception $e ) {
3647
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
3648
			}
3649
		}
3650
	}
3651
3652
	/**
3653
	 * Updates an invoice status.
3654
	 */
3655
	public function update_status( $new_status = false, $note = '', $manual = false ) {
3656
3657
		// Fires before updating a status.
3658
		do_action( 'wpinv_before_invoice_status_change', $this->get_id(), $new_status, $this->get_status( 'edit' ) );
3659
3660
		// Update the status.
3661
		$this->set_status( $new_status, $note, $manual );
3662
3663
		// Save the order.
3664
		return $this->save();
3665
3666
	}
3667
3668
	/**
3669
	 * @deprecated
3670
	 */
3671
	public function refresh_item_ids() {
3672
        $item_ids = implode( ',', array_unique( array_keys( $this->get_items() ) ) );
3673
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
3674
	}
3675
3676
	/**
3677
	 * @deprecated
3678
	 */
3679
	public function update_items( $temp = false ) {
3680
3681
		$this->set_items( $this->get_items() );
3682
3683
		if ( ! $temp ) {
3684
			$this->save();
3685
		}
3686
3687
        return $this;
3688
	}
3689
3690
	/**
3691
	 * @deprecated
3692
	 */
3693
    public function validate_discount() {
3694
3695
        $discount_code = $this->get_discount_code();
3696
3697
        if ( empty( $discount_code ) ) {
3698
            return false;
3699
        }
3700
3701
        $discount = wpinv_get_discount_obj( $discount_code );
3702
3703
        // Ensure it is active.
3704
        return $discount->exists();
3705
3706
    }
3707
3708
	/**
3709
	 * Refunds an invoice.
3710
	 */
3711
    public function refund() {
3712
		$this->set_status( 'wpi-refunded' );
3713
        $this->save();
3714
	}
3715
3716
	/**
3717
	 * Marks an invoice as paid.
3718
	 * 
3719
	 * @param string $transaction_id
3720
	 */
3721
    public function mark_paid( $transaction_id = null, $note = '' ) {
3722
3723
		// Set the transaction id.
3724
		if ( empty( $transaction_id ) ) {
3725
			$transaction_id = $this->generate_key('trans_');
3726
		}
3727
3728
		if ( ! $this->get_transaction_id() ) {
3729
			$this->set_transaction_id( $transaction_id );
3730
		}
3731
3732
		if ( $this->is_paid() && 'wpi-processing' != $this->get_status() ) {
3733
			return $this->save();
3734
		}
3735
3736
		// Set the completed date.
3737
		$this->set_date_completed( current_time( 'mysql' ) );
3738
3739
		// Set the new status.
3740
		if ( $this->is_renewal() ) {
3741
3742
			$_note = sprintf(
3743
				__( 'Renewed via %s', 'invoicing' ),
3744
				$this->get_gateway_title() . empty( $note ) ? '' : " ($note)"
3745
			);
3746
3747
			if ( 'none' == $this->get_gateway() ) {
3748
				$_note = $note;
3749
			}
3750
3751
			$this->set_status( 'wpi-renewal', $_note );
3752
3753
		} else {
3754
3755
			$_note = sprintf(
3756
				__( 'Paid via %s', 'invoicing' ),
3757
				$this->get_gateway_title() . empty( $note ) ? '' : " ($note)"
3758
			);
3759
3760
			if ( 'none' == $this->get_gateway() ) {
3761
				$_note = $note;
3762
			}
3763
3764
			$this->set_status( 'publish',$_note );
3765
3766
		}
3767
3768
		// Set checkout mode.
3769
		$mode = wpinv_is_test_mode( $this->get_gateway() ) ? 'test' : 'live';
3770
		$this->set_mode( $mode );
3771
3772
		// Save the invoice.
3773
        $this->save();
3774
	}
3775
3776
3777
	/**
3778
	 * Save data to the database.
3779
	 *
3780
	 * @since 1.0.19
3781
	 * @return int invoice ID
3782
	 */
3783
	public function save() {
3784
		$this->maybe_set_date_paid();
3785
		parent::save();
3786
		$this->clear_cache();
3787
		$this->status_transition();
3788
		return $this->get_id();
3789
	}
3790
3791
	/**
3792
     * Clears the subscription's cache.
3793
     */
3794
    public function clear_cache() {
3795
		wp_cache_delete( $this->get_key(), 'getpaid_invoice_keys_to_invoice_ids' );
3796
		wp_cache_delete( $this->get_number(), 'getpaid_invoice_numbers_to_invoice_ids' );
3797
		wp_cache_delete( $this->get_transaction_id(), 'getpaid_invoice_transaction_ids_to_invoice_ids' );
3798
	}
3799
3800
}
3801