Passed
Pull Request — master (#412)
by Brian
04:08
created

WPInv_Invoice::is_free_trial_from_discount()   A

Complexity

Conditions 2
Paths 2

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

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

3555
        /** @scrutinizer ignore-deprecated */ $this->update_items( $temp );
Loading history...
3556
        $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

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