Issues (850)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/class-wpinv-invoice.php (1 issue)

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
		'customer_id'            => 0,
39
		'status'                 => 'wpi-pending',
40
		'version'                => '',
41
		'date_created'           => null,
42
        'date_modified'          => null,
43
        'due_date'               => null,
44
        'completed_date'         => null,
45
        'number'                 => '',
46
        'title'                  => '',
47
        'path'                   => '',
48
        'key'                    => '',
49
        'description'            => '',
50
        'author'                 => 1,
51
        'type'                   => 'invoice',
52
        'post_type'              => 'wpi_invoice',
53
        'mode'                   => 'live',
54
        'user_ip'                => null,
55
        'first_name'             => null,
56
        'last_name'              => null,
57
        'phone'                  => null,
58
        'email'                  => null,
59
        'country'                => null,
60
        'city'                   => null,
61
        'state'                  => null,
62
        'zip'                    => null,
63
        'company'                => null,
64
		'company_id'             => null,
65
        'vat_number'             => null,
66
        'vat_rate'               => null,
67
        'address'                => null,
68
        'address_confirmed'      => false,
69
        'shipping'               => null,
70
		'subtotal'               => 0,
71
        'total_discount'         => 0,
72
        'total_tax'              => 0,
73
		'total_fees'             => 0,
74
		'total'                  => 0,
75
        'fees'                   => array(),
76
        'discounts'              => array(),
77
        'taxes'                  => array(),
78
        'items'                  => array(),
79
        'payment_form'           => 1,
80
        'submission_id'          => null,
81
        'discount_code'          => null,
82
        'gateway'                => 'none',
83
        'transaction_id'         => '',
84
        'currency'               => '',
85
        'disable_taxes'          => false,
86
		'subscription_id'        => null,
87
		'remote_subscription_id' => null,
88
		'is_anonymized'          => false,
89
		'is_viewed'              => false,
90
		'email_cc'               => '',
91
		'template'               => 'quantity', // hours, amount only
92
		'created_via'            => null,
93
    );
94
95
    /**
96
	 * Stores meta in cache for future reads.
97
	 *
98
	 * A group must be set to to enable caching.
99
	 *
100
	 * @var string
101
	 */
102
	protected $cache_group = 'getpaid_invoices';
103
104
    /**
105
     * Stores a reference to the original WP_Post object
106
     *
107
     * @var WP_Post
108
     */
109
    protected $post = null;
110
111
    /**
112
     * Stores a reference to the recurring item id instead of looping through the items.
113
     *
114
     * @var int
115
     */
116
	protected $recurring_item = null;
117
118
	/**
119
     * Stores an array of item totals.
120
	 *
121
	 * e.g $totals['discount'] = array(
122
	 *      'initial'   => 10,
123
	 *      'recurring' => 10,
124
	 * )
125
     *
126
     * @var array
127
     */
128
	protected $totals = array();
129
130
	/**
131
     * Tax rate.
132
	 *
133
     * @var float
134
     */
135
	protected $tax_rate = 0;
136
137
	/**
138
	 * Stores the status transition information.
139
	 *
140
	 * @since 1.0.19
141
	 * @var bool|array
142
	 */
143
	protected $status_transition = false;
144
145
    /**
146
	 * Get the invoice if ID is passed, otherwise the invoice is new and empty.
147
	 *
148
	 * @param  int|string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, transaction id, number or object to read.
149
	 */
150
    public function __construct( $invoice = 0 ) {
151
152
        parent::__construct( $invoice );
153
154
		if ( ! empty( $invoice ) && is_numeric( $invoice ) && getpaid_is_invoice_post_type( get_post_type( (int) $invoice ) ) ) {
155
			$this->set_id( (int) $invoice );
156
		} elseif ( $invoice instanceof self ) {
157
			$this->set_id( $invoice->get_id() );
158
		} elseif ( ! empty( $invoice->ID ) ) {
159
			$this->set_id( $invoice->ID );
160
		} elseif ( is_array( $invoice ) ) {
161
			$this->set_props( $invoice );
162
163
			if ( isset( $invoice['ID'] ) ) {
164
				$this->set_id( $invoice['ID'] );
165
			}
166
} elseif ( is_string( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'key' ) ) {
167
			$this->set_id( $invoice_id );
168
		} elseif ( is_string( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'number' ) ) {
169
			$this->set_id( $invoice_id );
170
		} elseif ( is_string( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'transaction_id' ) ) {
171
			$this->set_id( $invoice_id );
172
		} else {
173
			$this->set_object_read( true );
174
		}
175
176
        // Load the datastore.
177
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
178
179
		if ( $this->get_id() > 0 ) {
180
            $this->post = get_post( $this->get_id() );
181
            $this->ID   = $this->get_id();
182
			$this->data_store->read( $this );
183
        }
184
185
    }
186
187
    /**
188
	 * Given an invoice key/number, it returns its id.
189
	 *
190
	 *
191
	 * @static
192
	 * @param string $value The invoice key or number
193
	 * @param string $field Either key, transaction_id or number.
194
	 * @since 1.0.15
195
	 * @return int
196
	 */
197
	public static function get_invoice_id_by_field( $value, $field = 'key' ) {
198
        global $wpdb;
199
200
		// Trim the value.
201
		$value = trim( $value );
202
203
		if ( empty( $value ) ) {
204
			return 0;
205
		}
206
207
        // Valid fields.
208
        $fields = array( 'key', 'number', 'transaction_id' );
209
210
		// Ensure a field has been passed.
211
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
212
			return 0;
213
		}
214
215
		// Maybe retrieve from the cache.
216
		$invoice_id   = wp_cache_get( $value, "getpaid_invoice_{$field}s_to_invoice_ids" );
217
		if ( false !== $invoice_id ) {
218
			return $invoice_id;
219
		}
220
221
        // Fetch from the db.
222
        $table       = $wpdb->prefix . 'getpaid_invoices';
223
		$db_field    = 'key' === $field ? 'invoice_key' : $field;
224
        $invoice_id  = (int) $wpdb->get_var(
225
            $wpdb->prepare( "SELECT `post_id` FROM $table WHERE `$db_field`=%s LIMIT 1", $value )
226
        );
227
228
		// Update the cache with our data
229
		wp_cache_set( $value, $invoice_id, "getpaid_invoice_{$field}s_to_invoice_ids" );
230
231
		return $invoice_id;
232
    }
233
234
    /**
235
     * Checks if an invoice key is set.
236
     */
237
    public function _isset( $key ) {
238
        return isset( $this->data[ $key ] ) || method_exists( $this, "get_$key" );
239
    }
240
241
    /*
242
	|--------------------------------------------------------------------------
243
	| CRUD methods
244
	|--------------------------------------------------------------------------
245
	|
246
	| Methods which create, read, update and delete items from the database.
247
	|
248
    */
249
250
    /*
251
	|--------------------------------------------------------------------------
252
	| Getters
253
	|--------------------------------------------------------------------------
254
    */
255
256
    /**
257
	 * Get parent invoice ID.
258
	 *
259
	 * @since 1.0.19
260
	 * @param  string $context View or edit context.
261
	 * @return int
262
	 */
263
	public function get_parent_id( $context = 'view' ) {
264
		return (int) $this->get_prop( 'parent_id', $context );
265
    }
266
267
    /**
268
	 * Get parent invoice.
269
	 *
270
	 * @since 1.0.19
271
	 * @return WPInv_Invoice
272
	 */
273
    public function get_parent_payment() {
274
        return new WPInv_Invoice( $this->get_parent_id() );
275
    }
276
277
    /**
278
	 * Alias for self::get_parent_payment().
279
	 *
280
	 * @since 1.0.19
281
	 * @return WPInv_Invoice
282
	 */
283
    public function get_parent() {
284
        return $this->get_parent_payment();
285
    }
286
287
    /**
288
	 * Get invoice status.
289
	 *
290
	 * @since 1.0.19
291
	 * @param  string $context View or edit context.
292
	 * @return string
293
	 */
294
	public function get_status( $context = 'view' ) {
295
		return $this->get_prop( 'status', $context );
296
	}
297
298
	/**
299
	 * Retrieves an array of possible invoice statuses.
300
	 *
301
	 * @since 1.0.19
302
	 * @return array
303
	 */
304
	public function get_all_statuses() {
305
		return wpinv_get_invoice_statuses( true, true, $this );
306
    }
307
308
    /**
309
	 * Get invoice status nice name.
310
	 *
311
	 * @since 1.0.19
312
	 * @return string
313
	 */
314
    public function get_status_nicename() {
315
		$statuses = $this->get_all_statuses();
316
317
        $status = isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : $this->get_status();
318
319
        return apply_filters( 'wpinv_get_invoice_status_nicename', $status, $this );
320
    }
321
322
	/**
323
	 * Retrieves the invoice status class
324
	 *
325
	 * @since  1.0.19
326
	 * @return string
327
	 */
328
	public function get_status_class() {
329
		$statuses = getpaid_get_invoice_status_classes();
330
		return isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : 'bg-dark text-white';
331
	}
332
333
	/**
334
     * Retrieves the invoice status label html
335
     *
336
     * @since  1.0.0
337
     * @return string
338
     */
339
    public function get_status_label_html() {
340
341
		$status_label = sanitize_text_field( $this->get_status_nicename() );
342
		$status       = sanitize_html_class( $this->get_status() );
343
		$class        = esc_attr( $this->get_status_class() );
344
345
		return "<span class='bsui'><span class='badge $class $status'>$status_label</span></span>";
346
	}
347
348
    /**
349
	 * Get plugin version when the invoice was created.
350
	 *
351
	 * @since 1.0.19
352
	 * @param  string $context View or edit context.
353
	 * @return string
354
	 */
355
	public function get_version( $context = 'view' ) {
356
		return $this->get_prop( 'version', $context );
357
	}
358
359
	/**
360
	 * @deprecated
361
	 */
362
	public function get_invoice_date( $format = true ) {
363
		$date      = getpaid_format_date( $this->get_date_completed() );
364
		$date      = empty( $date ) ? $this->get_date_created() : $this->get_date_completed();
365
		$formatted = getpaid_format_date( $date );
366
367
		if ( $format ) {
368
			return $formatted;
369
		}
370
371
		return empty( $formatted ) ? '' : $date;
372
373
    }
374
375
    /**
376
	 * Get date when the invoice was created.
377
	 *
378
	 * @since 1.0.19
379
	 * @param  string $context View or edit context.
380
	 * @return string
381
	 */
382
	public function get_date_created( $context = 'view' ) {
383
		return $this->get_prop( 'date_created', $context );
384
	}
385
386
	/**
387
	 * Alias for self::get_date_created().
388
	 *
389
	 * @since 1.0.19
390
	 * @param  string $context View or edit context.
391
	 * @return string
392
	 */
393
	public function get_created_date( $context = 'view' ) {
394
		return $this->get_date_created( $context );
395
    }
396
397
    /**
398
	 * Get GMT date when the invoice was created.
399
	 *
400
	 * @since 1.0.19
401
	 * @param  string $context View or edit context.
402
	 * @return string
403
	 */
404
	public function get_date_created_gmt( $context = 'view' ) {
405
        $date = $this->get_date_created( $context );
406
407
        if ( $date ) {
408
            $date = get_gmt_from_date( $date );
409
        }
410
		return $date;
411
    }
412
413
    /**
414
	 * Get date when the invoice was last modified.
415
	 *
416
	 * @since 1.0.19
417
	 * @param  string $context View or edit context.
418
	 * @return string
419
	 */
420
	public function get_date_modified( $context = 'view' ) {
421
		return $this->get_prop( 'date_modified', $context );
422
	}
423
424
	/**
425
	 * Alias for self::get_date_modified().
426
	 *
427
	 * @since 1.0.19
428
	 * @param  string $context View or edit context.
429
	 * @return string
430
	 */
431
	public function get_modified_date( $context = 'view' ) {
432
		return $this->get_date_modified( $context );
433
    }
434
435
    /**
436
	 * Get GMT date when the invoice was last modified.
437
	 *
438
	 * @since 1.0.19
439
	 * @param  string $context View or edit context.
440
	 * @return string
441
	 */
442
	public function get_date_modified_gmt( $context = 'view' ) {
443
        $date = $this->get_date_modified( $context );
444
445
        if ( $date ) {
446
            $date = get_gmt_from_date( $date );
447
        }
448
		return $date;
449
    }
450
451
    /**
452
	 * Get the invoice due date.
453
	 *
454
	 * @since 1.0.19
455
	 * @param  string $context View or edit context.
456
	 * @return string
457
	 */
458
	public function get_due_date( $context = 'view' ) {
459
		return $this->get_prop( 'due_date', $context );
460
    }
461
462
    /**
463
	 * Alias for self::get_due_date().
464
	 *
465
	 * @since 1.0.19
466
	 * @param  string $context View or edit context.
467
	 * @return string
468
	 */
469
	public function get_date_due( $context = 'view' ) {
470
		return $this->get_due_date( $context );
471
    }
472
473
    /**
474
	 * Get the invoice GMT due date.
475
	 *
476
	 * @since 1.0.19
477
	 * @param  string $context View or edit context.
478
	 * @return string
479
	 */
480
	public function get_due_date_gmt( $context = 'view' ) {
481
        $date = $this->get_due_date( $context );
482
483
        if ( $date ) {
484
            $date = get_gmt_from_date( $date );
485
        }
486
		return $date;
487
    }
488
489
    /**
490
	 * Alias for self::get_due_date_gmt().
491
	 *
492
	 * @since 1.0.19
493
	 * @param  string $context View or edit context.
494
	 * @return string
495
	 */
496
	public function get_gmt_date_due( $context = 'view' ) {
497
		return $this->get_due_date_gmt( $context );
498
    }
499
500
    /**
501
	 * Get date when the invoice was completed.
502
	 *
503
	 * @since 1.0.19
504
	 * @param  string $context View or edit context.
505
	 * @return string
506
	 */
507
	public function get_completed_date( $context = 'view' ) {
508
		return $this->get_prop( 'completed_date', $context );
509
    }
510
511
    /**
512
	 * Alias for self::get_completed_date().
513
	 *
514
	 * @since 1.0.19
515
	 * @param  string $context View or edit context.
516
	 * @return string
517
	 */
518
	public function get_date_completed( $context = 'view' ) {
519
		return $this->get_completed_date( $context );
520
    }
521
522
    /**
523
	 * Get GMT date when the invoice was was completed.
524
	 *
525
	 * @since 1.0.19
526
	 * @param  string $context View or edit context.
527
	 * @return string
528
	 */
529
	public function get_completed_date_gmt( $context = 'view' ) {
530
        $date = $this->get_completed_date( $context );
531
532
        if ( $date ) {
533
            $date = get_gmt_from_date( $date );
534
        }
535
		return $date;
536
    }
537
538
    /**
539
	 * Alias for self::get_completed_date_gmt().
540
	 *
541
	 * @since 1.0.19
542
	 * @param  string $context View or edit context.
543
	 * @return string
544
	 */
545
	public function get_gmt_completed_date( $context = 'view' ) {
546
		return $this->get_completed_date_gmt( $context );
547
    }
548
549
    /**
550
	 * Get the invoice number.
551
	 *
552
	 * @since 1.0.19
553
	 * @param  string $context View or edit context.
554
	 * @return string
555
	 */
556
	public function get_number( $context = 'view' ) {
557
		$number = $this->get_prop( 'number', $context );
558
559
		if ( empty( $number ) ) {
560
			$number = $this->generate_number();
561
			$this->set_number( $this->generate_number() );
562
		}
563
564
		return $number;
565
    }
566
567
	/**
568
	 * Set the invoice number.
569
	 *
570
	 * @since 1.0.19
571
	 */
572
	public function maybe_set_number() {
573
        $number = $this->get_number();
574
575
        if ( empty( $number ) || $this->get_id() == $number ) {
576
			$this->set_number( $this->generate_number() );
577
        }
578
579
	}
580
581
    /**
582
	 * Get the invoice key.
583
	 *
584
	 * @since 1.0.19
585
	 * @param  string $context View or edit context.
586
	 * @return string
587
	 */
588
	public function get_key( $context = 'view' ) {
589
        return $this->get_prop( 'key', $context );
590
	}
591
592
	/**
593
	 * Set the invoice key.
594
	 *
595
	 * @since 1.0.19
596
	 */
597
	public function maybe_set_key() {
598
        $key = $this->get_key();
599
600
        if ( empty( $key ) ) {
601
            $key = $this->generate_key( $this->get_type() . '_' );
602
            $this->set_key( $key );
603
        }
604
605
    }
606
607
    /**
608
	 * Get the invoice type.
609
	 *
610
	 * @since 1.0.19
611
	 * @param  string $context View or edit context.
612
	 * @return string
613
	 */
614
	public function get_type( $context = 'view' ) {
615
        return $this->get_prop( 'type', $context );
616
	}
617
618
	/**
619
	 * Returns the post type name.
620
	 *
621
	 * @since 1.0.19
622
	 * @return string
623
	 */
624
	public function get_invoice_quote_type() {
625
        return getpaid_get_post_type_label( $this->get_post_type(), false );
626
    }
627
628
    /**
629
	 * Get the invoice post type label.
630
	 *
631
	 * @since 1.0.19
632
	 * @param  string $context View or edit context.
633
	 * @return string
634
	 */
635
	public function get_label( $context = 'view' ) {
636
        return getpaid_get_post_type_label( $this->get_post_type( $context ), false );
637
	}
638
639
	/**
640
	 * Get the invoice post type.
641
	 *
642
	 * @since 1.0.19
643
	 * @param  string $context View or edit context.
644
	 * @return string
645
	 */
646
	public function get_post_type( $context = 'view' ) {
647
        return $this->get_prop( 'post_type', $context );
648
    }
649
650
    /**
651
	 * Get the invoice mode.
652
	 *
653
	 * @since 1.0.19
654
	 * @param  string $context View or edit context.
655
	 * @return string
656
	 */
657
	public function get_mode( $context = 'view' ) {
658
        return $this->get_prop( 'mode', $context );
659
    }
660
661
    /**
662
	 * Get the invoice path.
663
	 *
664
	 * @since 1.0.19
665
	 * @param  string $context View or edit context.
666
	 * @return string
667
	 */
668
	public function get_path( $context = 'view' ) {
669
        $path   = $this->get_prop( 'path', $context );
670
		$prefix = $this->get_type();
671
672
		if ( 0 !== strpos( $path, $prefix ) ) {
673
			$path = sanitize_title( $prefix . '-' . $this->get_id() );
674
			$this->set_path( $path );
675
		}
676
677
		return $path;
678
    }
679
680
    /**
681
	 * Get the invoice name/title.
682
	 *
683
	 * @since 1.0.19
684
	 * @param  string $context View or edit context.
685
	 * @return string
686
	 */
687
	public function get_name( $context = 'view' ) {
688
        return $this->get_prop( 'title', $context );
689
    }
690
691
    /**
692
	 * Alias of self::get_name().
693
	 *
694
	 * @since 1.0.19
695
	 * @param  string $context View or edit context.
696
	 * @return string
697
	 */
698
	public function get_title( $context = 'view' ) {
699
		return $this->get_name( $context );
700
    }
701
702
    /**
703
	 * Get the invoice description.
704
	 *
705
	 * @since 1.0.19
706
	 * @param  string $context View or edit context.
707
	 * @return string
708
	 */
709
	public function get_description( $context = 'view' ) {
710
		return $this->get_prop( 'description', $context );
711
    }
712
713
    /**
714
	 * Alias of self::get_description().
715
	 *
716
	 * @since 1.0.19
717
	 * @param  string $context View or edit context.
718
	 * @return string
719
	 */
720
	public function get_excerpt( $context = 'view' ) {
721
		return $this->get_description( $context );
722
    }
723
724
    /**
725
	 * Alias of self::get_description().
726
	 *
727
	 * @since 1.0.19
728
	 * @param  string $context View or edit context.
729
	 * @return string
730
	 */
731
	public function get_summary( $context = 'view' ) {
732
		return $this->get_description( $context );
733
    }
734
735
    /**
736
	 * Returns the user info.
737
	 *
738
	 * @since 1.0.19
739
     * @param  string $context View or edit context.
740
	 * @return array
741
	 */
742
    public function get_user_info( $context = 'view' ) {
743
744
        $user_info = array(
745
            'user_id'    => $this->get_user_id( $context ),
746
            'email'      => $this->get_email( $context ),
747
            'first_name' => $this->get_first_name( $context ),
748
            'last_name'  => $this->get_last_name( $context ),
749
            'address'    => $this->get_address( $context ),
750
            'phone'      => $this->get_phone( $context ),
751
            'city'       => $this->get_city( $context ),
752
            'country'    => $this->get_country( $context ),
753
            'state'      => $this->get_state( $context ),
754
            'zip'        => $this->get_zip( $context ),
755
            'company'    => $this->get_company( $context ),
756
			'company_id' => $this->get_company_id( $context ),
757
            'vat_number' => $this->get_vat_number( $context ),
758
            'discount'   => $this->get_discount_code( $context ),
759
		);
760
761
		return apply_filters( 'wpinv_user_info', $user_info, $this->get_id(), $this );
762
763
    }
764
765
    /**
766
	 * Get the user id.
767
	 *
768
	 * @since 1.0.19
769
	 * @param  string $context View or edit context.
770
	 * @return int
771
	 */
772
	public function get_author( $context = 'view' ) {
773
		return (int) $this->get_prop( 'author', $context );
774
    }
775
776
    /**
777
	 * Alias of self::get_author().
778
	 *
779
	 * @since 1.0.19
780
	 * @param  string $context View or edit context.
781
	 * @return int
782
	 */
783
	public function get_user_id( $context = 'view' ) {
784
		return $this->get_author( $context );
785
    }
786
787
     /**
788
	 * Get customer ID.
789
	 *
790
	 * @since 1.0.19
791
	 * @param  string $context View or edit context.
792
	 * @return int
793
	 */
794
	public function get_customer_id( $context = 'view' ) {
795
		return (int) $this->get_prop( 'customer_id', $context );
796
    }
797
798
    /**
799
	 * Get the customer's ip.
800
	 *
801
	 * @since 1.0.19
802
	 * @param  string $context View or edit context.
803
	 * @return string
804
	 */
805
	public function get_ip( $context = 'view' ) {
806
		return $this->get_prop( 'user_ip', $context );
807
    }
808
809
    /**
810
	 * Alias of self::get_ip().
811
	 *
812
	 * @since 1.0.19
813
	 * @param  string $context View or edit context.
814
	 * @return string
815
	 */
816
	public function get_user_ip( $context = 'view' ) {
817
		return $this->get_ip( $context );
818
    }
819
820
     /**
821
	 * Alias of self::get_ip().
822
	 *
823
	 * @since 1.0.19
824
	 * @param  string $context View or edit context.
825
	 * @return string
826
	 */
827
	public function get_customer_ip( $context = 'view' ) {
828
		return $this->get_ip( $context );
829
    }
830
831
    /**
832
	 * Get the customer's first name.
833
	 *
834
	 * @since 1.0.19
835
	 * @param  string $context View or edit context.
836
	 * @return string
837
	 */
838
	public function get_first_name( $context = 'view' ) {
839
		return $this->get_prop( 'first_name', $context );
840
    }
841
842
    /**
843
	 * Alias of self::get_first_name().
844
	 *
845
	 * @since 1.0.19
846
	 * @param  string $context View or edit context.
847
	 * @return string
848
	 */
849
	public function get_user_first_name( $context = 'view' ) {
850
		return $this->get_first_name( $context );
851
    }
852
853
     /**
854
	 * Alias of self::get_first_name().
855
	 *
856
	 * @since 1.0.19
857
	 * @param  string $context View or edit context.
858
	 * @return string
859
	 */
860
	public function get_customer_first_name( $context = 'view' ) {
861
		return $this->get_first_name( $context );
862
    }
863
864
    /**
865
	 * Get the customer's last name.
866
	 *
867
	 * @since 1.0.19
868
	 * @param  string $context View or edit context.
869
	 * @return string
870
	 */
871
	public function get_last_name( $context = 'view' ) {
872
		return $this->get_prop( 'last_name', $context );
873
    }
874
875
    /**
876
	 * Alias of self::get_last_name().
877
	 *
878
	 * @since 1.0.19
879
	 * @param  string $context View or edit context.
880
	 * @return string
881
	 */
882
	public function get_user_last_name( $context = 'view' ) {
883
		return $this->get_last_name( $context );
884
    }
885
886
    /**
887
	 * Alias of self::get_last_name().
888
	 *
889
	 * @since 1.0.19
890
	 * @param  string $context View or edit context.
891
	 * @return string
892
	 */
893
	public function get_customer_last_name( $context = 'view' ) {
894
		return $this->get_last_name( $context );
895
    }
896
897
    /**
898
	 * Get the customer's full name.
899
	 *
900
	 * @since 1.0.19
901
	 * @param  string $context View or edit context.
902
	 * @return string
903
	 */
904
	public function get_full_name( $context = 'view' ) {
905
		$name = trim( $this->get_first_name( $context ) . ' ' . $this->get_last_name( $context ) );
906
907
		if ( ! $name ) {
908
			$user = get_userdata( $this->get_author( $context ) );
909
910
			if ( $user ) {
911
				$name = $user->display_name;
912
			}
913
		}
914
915
		if ( ! $name ) {
916
			$name = $this->get_email( $context );
917
		}
918
919
		return apply_filters( 'wpinv_invoice_user_full_name', $name, $this );
920
    }
921
922
    /**
923
	 * Alias of self::get_full_name().
924
	 *
925
	 * @since 1.0.19
926
	 * @param  string $context View or edit context.
927
	 * @return string
928
	 */
929
	public function get_user_full_name( $context = 'view' ) {
930
		return $this->get_full_name( $context );
931
    }
932
933
    /**
934
	 * Alias of self::get_full_name().
935
	 *
936
	 * @since 1.0.19
937
	 * @param  string $context View or edit context.
938
	 * @return string
939
	 */
940
	public function get_customer_full_name( $context = 'view' ) {
941
		return $this->get_full_name( $context );
942
    }
943
944
    /**
945
	 * Get the customer's phone number.
946
	 *
947
	 * @since 1.0.19
948
	 * @param  string $context View or edit context.
949
	 * @return string
950
	 */
951
	public function get_phone( $context = 'view' ) {
952
		return $this->get_prop( 'phone', $context );
953
    }
954
955
    /**
956
	 * Alias of self::get_phone().
957
	 *
958
	 * @since 1.0.19
959
	 * @param  string $context View or edit context.
960
	 * @return string
961
	 */
962
	public function get_phone_number( $context = 'view' ) {
963
		return $this->get_phone( $context );
964
    }
965
966
    /**
967
	 * Alias of self::get_phone().
968
	 *
969
	 * @since 1.0.19
970
	 * @param  string $context View or edit context.
971
	 * @return string
972
	 */
973
	public function get_user_phone( $context = 'view' ) {
974
		return $this->get_phone( $context );
975
    }
976
977
    /**
978
	 * Alias of self::get_phone().
979
	 *
980
	 * @since 1.0.19
981
	 * @param  string $context View or edit context.
982
	 * @return string
983
	 */
984
	public function get_customer_phone( $context = 'view' ) {
985
		return $this->get_phone( $context );
986
    }
987
988
    /**
989
	 * Get the customer's email address.
990
	 *
991
	 * @since 1.0.19
992
	 * @param  string $context View or edit context.
993
	 * @return string
994
	 */
995
	public function get_email( $context = 'view' ) {
996
		return $this->get_prop( 'email', $context );
997
    }
998
999
    /**
1000
	 * Alias of self::get_email().
1001
	 *
1002
	 * @since 1.0.19
1003
	 * @param  string $context View or edit context.
1004
	 * @return string
1005
	 */
1006
	public function get_email_address( $context = 'view' ) {
1007
		return $this->get_email( $context );
1008
    }
1009
1010
    /**
1011
	 * Alias of self::get_email().
1012
	 *
1013
	 * @since 1.0.19
1014
	 * @param  string $context View or edit context.
1015
	 * @return string
1016
	 */
1017
	public function get_user_email( $context = 'view' ) {
1018
		return $this->get_email( $context );
1019
    }
1020
1021
    /**
1022
	 * Alias of self::get_email().
1023
	 *
1024
	 * @since 1.0.19
1025
	 * @param  string $context View or edit context.
1026
	 * @return string
1027
	 */
1028
	public function get_customer_email( $context = 'view' ) {
1029
		return $this->get_email( $context );
1030
    }
1031
1032
    /**
1033
	 * Get the customer's country.
1034
	 *
1035
	 * @since 1.0.19
1036
	 * @param  string $context View or edit context.
1037
	 * @return string
1038
	 */
1039
	public function get_country( $context = 'view' ) {
1040
		$country = $this->get_prop( 'country', $context );
1041
		return empty( $country ) ? wpinv_get_default_country() : $country;
1042
    }
1043
1044
    /**
1045
	 * Alias of self::get_country().
1046
	 *
1047
	 * @since 1.0.19
1048
	 * @param  string $context View or edit context.
1049
	 * @return string
1050
	 */
1051
	public function get_user_country( $context = 'view' ) {
1052
		return $this->get_country( $context );
1053
    }
1054
1055
    /**
1056
	 * Alias of self::get_country().
1057
	 *
1058
	 * @since 1.0.19
1059
	 * @param  string $context View or edit context.
1060
	 * @return string
1061
	 */
1062
	public function get_customer_country( $context = 'view' ) {
1063
		return $this->get_country( $context );
1064
    }
1065
1066
    /**
1067
	 * Get the customer's state.
1068
	 *
1069
	 * @since 1.0.19
1070
	 * @param  string $context View or edit context.
1071
	 * @return string
1072
	 */
1073
	public function get_state( $context = 'view' ) {
1074
		$state = $this->get_prop( 'state', $context );
1075
		return empty( $state ) ? wpinv_get_default_state() : $state;
1076
    }
1077
1078
    /**
1079
	 * Alias of self::get_state().
1080
	 *
1081
	 * @since 1.0.19
1082
	 * @param  string $context View or edit context.
1083
	 * @return string
1084
	 */
1085
	public function get_user_state( $context = 'view' ) {
1086
		return $this->get_state( $context );
1087
    }
1088
1089
    /**
1090
	 * Alias of self::get_state().
1091
	 *
1092
	 * @since 1.0.19
1093
	 * @param  string $context View or edit context.
1094
	 * @return string
1095
	 */
1096
	public function get_customer_state( $context = 'view' ) {
1097
		return $this->get_state( $context );
1098
    }
1099
1100
    /**
1101
	 * Get the customer's city.
1102
	 *
1103
	 * @since 1.0.19
1104
	 * @param  string $context View or edit context.
1105
	 * @return string
1106
	 */
1107
	public function get_city( $context = 'view' ) {
1108
		return $this->get_prop( 'city', $context );
1109
    }
1110
1111
    /**
1112
	 * Alias of self::get_city().
1113
	 *
1114
	 * @since 1.0.19
1115
	 * @param  string $context View or edit context.
1116
	 * @return string
1117
	 */
1118
	public function get_user_city( $context = 'view' ) {
1119
		return $this->get_city( $context );
1120
    }
1121
1122
    /**
1123
	 * Alias of self::get_city().
1124
	 *
1125
	 * @since 1.0.19
1126
	 * @param  string $context View or edit context.
1127
	 * @return string
1128
	 */
1129
	public function get_customer_city( $context = 'view' ) {
1130
		return $this->get_city( $context );
1131
    }
1132
1133
    /**
1134
	 * Get the customer's zip.
1135
	 *
1136
	 * @since 1.0.19
1137
	 * @param  string $context View or edit context.
1138
	 * @return string
1139
	 */
1140
	public function get_zip( $context = 'view' ) {
1141
		return $this->get_prop( 'zip', $context );
1142
    }
1143
1144
    /**
1145
	 * Alias of self::get_zip().
1146
	 *
1147
	 * @since 1.0.19
1148
	 * @param  string $context View or edit context.
1149
	 * @return string
1150
	 */
1151
	public function get_user_zip( $context = 'view' ) {
1152
		return $this->get_zip( $context );
1153
    }
1154
1155
    /**
1156
	 * Alias of self::get_zip().
1157
	 *
1158
	 * @since 1.0.19
1159
	 * @param  string $context View or edit context.
1160
	 * @return string
1161
	 */
1162
	public function get_customer_zip( $context = 'view' ) {
1163
		return $this->get_zip( $context );
1164
    }
1165
1166
    /**
1167
	 * Get the customer's company.
1168
	 *
1169
	 * @since 1.0.19
1170
	 * @param  string $context View or edit context.
1171
	 * @return string
1172
	 */
1173
	public function get_company( $context = 'view' ) {
1174
		return $this->get_prop( 'company', $context );
1175
    }
1176
1177
    /**
1178
	 * Alias of self::get_company().
1179
	 *
1180
	 * @since 1.0.19
1181
	 * @param  string $context View or edit context.
1182
	 * @return string
1183
	 */
1184
	public function get_user_company( $context = 'view' ) {
1185
		return $this->get_company( $context );
1186
    }
1187
1188
    /**
1189
	 * Alias of self::get_company().
1190
	 *
1191
	 * @since 1.0.19
1192
	 * @param  string $context View or edit context.
1193
	 * @return string
1194
	 */
1195
	public function get_customer_company( $context = 'view' ) {
1196
		return $this->get_company( $context );
1197
    }
1198
1199
	/**
1200
	 * Get the customer's company id.
1201
	 *
1202
	 * @since 1.0.19
1203
	 * @param  string $context View or edit context.
1204
	 * @return string
1205
	 */
1206
	public function get_company_id( $context = 'view' ) {
1207
		return $this->get_prop( 'company_id', $context );
1208
    }
1209
1210
    /**
1211
	 * Get the customer's vat number.
1212
	 *
1213
	 * @since 1.0.19
1214
	 * @param  string $context View or edit context.
1215
	 * @return string
1216
	 */
1217
	public function get_vat_number( $context = 'view' ) {
1218
		return $this->get_prop( 'vat_number', $context );
1219
    }
1220
1221
    /**
1222
	 * Alias of self::get_vat_number().
1223
	 *
1224
	 * @since 1.0.19
1225
	 * @param  string $context View or edit context.
1226
	 * @return string
1227
	 */
1228
	public function get_user_vat_number( $context = 'view' ) {
1229
		return $this->get_vat_number( $context );
1230
    }
1231
1232
    /**
1233
	 * Alias of self::get_vat_number().
1234
	 *
1235
	 * @since 1.0.19
1236
	 * @param  string $context View or edit context.
1237
	 * @return string
1238
	 */
1239
	public function get_customer_vat_number( $context = 'view' ) {
1240
		return $this->get_vat_number( $context );
1241
    }
1242
1243
    /**
1244
	 * Get the customer's vat rate.
1245
	 *
1246
	 * @since 1.0.19
1247
	 * @param  string $context View or edit context.
1248
	 * @return string
1249
	 */
1250
	public function get_vat_rate( $context = 'view' ) {
1251
		return $this->get_prop( 'vat_rate', $context );
1252
    }
1253
1254
    /**
1255
	 * Alias of self::get_vat_rate().
1256
	 *
1257
	 * @since 1.0.19
1258
	 * @param  string $context View or edit context.
1259
	 * @return string
1260
	 */
1261
	public function get_user_vat_rate( $context = 'view' ) {
1262
		return $this->get_vat_rate( $context );
1263
    }
1264
1265
    /**
1266
	 * Alias of self::get_vat_rate().
1267
	 *
1268
	 * @since 1.0.19
1269
	 * @param  string $context View or edit context.
1270
	 * @return string
1271
	 */
1272
	public function get_customer_vat_rate( $context = 'view' ) {
1273
		return $this->get_vat_rate( $context );
1274
    }
1275
1276
    /**
1277
	 * Get the customer's address.
1278
	 *
1279
	 * @since 1.0.19
1280
	 * @param  string $context View or edit context.
1281
	 * @return string
1282
	 */
1283
	public function get_address( $context = 'view' ) {
1284
		return $this->get_prop( 'address', $context );
1285
    }
1286
1287
    /**
1288
	 * Alias of self::get_address().
1289
	 *
1290
	 * @since 1.0.19
1291
	 * @param  string $context View or edit context.
1292
	 * @return string
1293
	 */
1294
	public function get_user_address( $context = 'view' ) {
1295
		return $this->get_address( $context );
1296
    }
1297
1298
    /**
1299
	 * Alias of self::get_address().
1300
	 *
1301
	 * @since 1.0.19
1302
	 * @param  string $context View or edit context.
1303
	 * @return string
1304
	 */
1305
	public function get_customer_address( $context = 'view' ) {
1306
		return $this->get_address( $context );
1307
    }
1308
1309
    /**
1310
	 * Get whether the customer has viewed the invoice or not.
1311
	 *
1312
	 * @since 1.0.19
1313
	 * @param  string $context View or edit context.
1314
	 * @return bool
1315
	 */
1316
	public function get_is_viewed( $context = 'view' ) {
1317
		return (bool) $this->get_prop( 'is_viewed', $context );
1318
	}
1319
1320
	/**
1321
	 * Get other recipients for invoice communications.
1322
	 *
1323
	 * @since 1.0.19
1324
	 * @param  string $context View or edit context.
1325
	 * @return bool
1326
	 */
1327
	public function get_email_cc( $context = 'view' ) {
1328
		return $this->get_prop( 'email_cc', $context );
1329
	}
1330
1331
	/**
1332
	 * Get invoice template.
1333
	 *
1334
	 * @since 1.0.19
1335
	 * @param  string $context View or edit context.
1336
	 * @return bool
1337
	 */
1338
	public function get_template( $context = 'view' ) {
1339
		return $this->get_prop( 'template', $context );
1340
	}
1341
1342
	/**
1343
	 * Get invoice source.
1344
	 *
1345
	 * @since 1.0.19
1346
	 * @param  string $context View or edit context.
1347
	 * @return bool
1348
	 */
1349
	public function get_created_via( $context = 'view' ) {
1350
		return $this->get_prop( 'created_via', $context );
1351
	}
1352
1353
	/**
1354
	 * Get whether the customer has confirmed their address.
1355
	 *
1356
	 * @since 1.0.19
1357
	 * @param  string $context View or edit context.
1358
	 * @return bool
1359
	 */
1360
	public function get_address_confirmed( $context = 'view' ) {
1361
		return (bool) $this->get_prop( 'address_confirmed', $context );
1362
    }
1363
1364
    /**
1365
	 * Alias of self::get_address_confirmed().
1366
	 *
1367
	 * @since 1.0.19
1368
	 * @param  string $context View or edit context.
1369
	 * @return bool
1370
	 */
1371
	public function get_user_address_confirmed( $context = 'view' ) {
1372
		return $this->get_address_confirmed( $context );
1373
    }
1374
1375
    /**
1376
	 * Alias of self::get_address().
1377
	 *
1378
	 * @since 1.0.19
1379
	 * @param  string $context View or edit context.
1380
	 * @return bool
1381
	 */
1382
	public function get_customer_address_confirmed( $context = 'view' ) {
1383
		return $this->get_address_confirmed( $context );
1384
    }
1385
1386
	/**
1387
	 * Get the shipping address.
1388
	 *
1389
	 * @since 1.0.19
1390
	 * @return array|false
1391
	 */
1392
	public function get_shipping_address() {
1393
1394
		$shipping_address = get_post_meta( $this->get_id(), 'shipping_address', true );
1395
		return is_array( $shipping_address ) ? $shipping_address : false;
1396
    }
1397
1398
	/**
1399
	 * Check if the invoice has a shipping address.
1400
	 */
1401
	public function has_shipping_address() {
1402
		return false !== $this->get_shipping_address();
1403
    }
1404
1405
	/**
1406
	 * Get the shipping amount.
1407
	 *
1408
	 * @since 1.0.19
1409
	 * @param  string $context View or edit context.
1410
	 * @return float
1411
	 */
1412
	public function get_shipping( $context = 'view' ) {
1413
1414
		if ( $context = 'view' ) {
1415
			return floatval( $this->get_prop( 'shipping', $context ) );
1416
		}
1417
1418
		return $this->get_prop( 'shipping', $context );
1419
    }
1420
1421
	public function has_shipping() {
1422
		return defined( 'GETPAID_SHIPPING_CALCULATOR_VERSION' ) && $this->get_prop( 'shipping', 'edit' );
1423
    }
1424
1425
    /**
1426
	 * Get the invoice subtotal.
1427
	 *
1428
	 * @since 1.0.19
1429
	 * @param  string $context View or edit context.
1430
	 * @return float
1431
	 */
1432
	public function get_subtotal( $context = 'view' ) {
1433
        $subtotal = (float) $this->get_prop( 'subtotal', $context );
1434
1435
        // Backwards compatibility.
1436
        if ( is_bool( $context ) && $context ) {
1437
            return wpinv_price( $subtotal, $this->get_currency() );
1438
        }
1439
1440
        return $subtotal;
1441
    }
1442
1443
    /**
1444
	 * Get the invoice discount total.
1445
	 *
1446
	 * @since 1.0.19
1447
	 * @param  string $context View or edit context.
1448
	 * @return float
1449
	 */
1450
	public function get_total_discount( $context = 'view' ) {
1451
		return wpinv_round_amount( wpinv_sanitize_amount( $this->get_prop( 'total_discount', $context ) ) );
1452
    }
1453
1454
    /**
1455
	 * Get the invoice tax total.
1456
	 *
1457
	 * @since 1.0.19
1458
	 * @param  string $context View or edit context.
1459
	 * @return float
1460
	 */
1461
	public function get_total_tax( $context = 'view' ) {
1462
		return wpinv_round_amount( wpinv_sanitize_amount( $this->get_prop( 'total_tax', $context ) ) );
1463
	}
1464
1465
	/**
1466
	 * @deprecated
1467
	 */
1468
	public function get_final_tax( $currency = false ) {
1469
		$tax = $this->get_total_tax();
1470
1471
        if ( $currency ) {
1472
			return wpinv_price( $tax, $this->get_currency() );
1473
        }
1474
1475
        return $tax;
1476
    }
1477
1478
    /**
1479
	 * Get the invoice fees total.
1480
	 *
1481
	 * @since 1.0.19
1482
	 * @param  string $context View or edit context.
1483
	 * @return float
1484
	 */
1485
	public function get_total_fees( $context = 'view' ) {
1486
		return wpinv_round_amount( wpinv_sanitize_amount( $this->get_prop( 'total_fees', $context ) ) );
1487
    }
1488
1489
    /**
1490
	 * Alias for self::get_total_fees().
1491
	 *
1492
	 * @since 1.0.19
1493
	 * @param  string $context View or edit context.
1494
	 * @return float
1495
	 */
1496
	public function get_fees_total( $context = 'view' ) {
1497
		return $this->get_total_fees( $context );
1498
    }
1499
1500
    /**
1501
	 * Get the invoice total.
1502
	 *
1503
	 * @since 1.0.19
1504
     * @return float
1505
	 */
1506
	public function get_total( $context = 'view' ) {
1507
		$total = $this->get_prop( 'total', $context );
1508
1509
		if ( $this->has_shipping() && $context == 'view' ) {
1510
			$total = $this->get_prop( 'total', $context ) + $this->get_shipping( $context );
1511
		}
1512
1513
		return wpinv_round_amount( wpinv_sanitize_amount( $total ) );
1514
	}
1515
1516
	/**
1517
	 * Retrieves the non-recurring total of items.
1518
	 *
1519
	 * @since 2.3.0
1520
	 * @return float
1521
	 */
1522
	public function get_non_recurring_total() {
1523
1524
		$subtotal = 0;
1525
		foreach ( $this->get_items() as $item ) {
1526
			if ( ! $item->is_recurring() ) {
1527
				$subtotal += $item->get_sub_total();
1528
			}
1529
		}
1530
1531
		foreach ( $this->get_fees() as $fee ) {
1532
			if ( empty( $fee['recurring_fee'] ) ) {
1533
				$subtotal += wpinv_sanitize_amount( $fee['initial_fee'] );
1534
			}
1535
		}
1536
1537
		$subtotal = wpinv_round_amount( wpinv_sanitize_amount( $subtotal ) );
1538
        return apply_filters( 'wpinv_get_non_recurring_invoice_total', $subtotal, $this );
1539
1540
    }
1541
1542
	/**
1543
	 * Get the invoice totals.
1544
	 *
1545
	 * @since 1.0.19
1546
     * @return array
1547
	 */
1548
	public function get_totals() {
1549
		return $this->totals;
1550
    }
1551
1552
    /**
1553
	 * Get the initial invoice total.
1554
	 *
1555
	 * @since 1.0.19
1556
     * @param  string $context View or edit context.
1557
     * @return float
1558
	 */
1559
    public function get_initial_total() {
1560
1561
		if ( empty( $this->totals ) ) {
1562
			$this->recalculate_total();
1563
		}
1564
1565
		$tax      = $this->totals['tax']['initial'];
1566
		$fee      = $this->totals['fee']['initial'];
1567
		$discount = $this->totals['discount']['initial'];
1568
		$subtotal = $this->totals['subtotal']['initial'];
1569
		$total    = $tax + $fee - $discount + $subtotal;
1570
1571
		if ( 0 > $total ) {
1572
			$total = 0;
1573
		}
1574
1575
		$total = wpinv_round_amount( wpinv_sanitize_amount( $total ) );
1576
        return apply_filters( 'wpinv_get_initial_invoice_total', $total, $this );
1577
	}
1578
1579
	/**
1580
	 * Get the recurring invoice total.
1581
	 *
1582
	 * @since 1.0.19
1583
     * @param  string $context View or edit context.
1584
     * @return float
1585
	 */
1586
    public function get_recurring_total() {
1587
1588
		if ( empty( $this->totals ) ) {
1589
			$this->recalculate_total();
1590
		}
1591
1592
		$tax      = $this->totals['tax']['recurring'];
1593
		$fee      = $this->totals['fee']['recurring'];
1594
		$discount = $this->totals['discount']['recurring'];
1595
		$subtotal = $this->totals['subtotal']['recurring'];
1596
		$total    = $tax + $fee - $discount + $subtotal;
1597
1598
		if ( 0 > $total ) {
1599
			$total = 0;
1600
		}
1601
1602
		$total = wpinv_round_amount( wpinv_sanitize_amount( $total ) );
1603
        return apply_filters( 'wpinv_get_recurring_invoice_total', $total, $this );
1604
	}
1605
1606
	/**
1607
	 * Returns recurring payment details.
1608
	 *
1609
	 * @since 1.0.19
1610
     * @param  string $field Optionally provide a field to return.
1611
	 * @param string $currency Whether to include the currency.
1612
     * @return float|string
1613
	 */
1614
    public function get_recurring_details( $field = '', $currency = false ) {
1615
1616
		// Maybe recalculate totals.
1617
		if ( empty( $this->totals ) ) {
1618
			$this->recalculate_total();
1619
		}
1620
1621
		// Prepare recurring totals.
1622
        $data = apply_filters(
1623
			'wpinv_get_invoice_recurring_details',
1624
			array(
1625
				'cart_details' => $this->get_cart_details(),
1626
				'subtotal'     => $this->totals['subtotal']['recurring'],
1627
				'discount'     => $this->totals['discount']['recurring'],
1628
				'tax'          => $this->totals['tax']['recurring'],
1629
				'fee'          => $this->totals['fee']['recurring'],
1630
				'total'        => $this->get_recurring_total(),
1631
			),
1632
			$this,
1633
			$field,
1634
			$currency
1635
		);
1636
1637
        if ( isset( $data[ $field ] ) ) {
1638
            return ( $currency ? wpinv_price( $data[ $field ], $this->get_currency() ) : $data[ $field ] );
1639
        }
1640
1641
        return $data;
1642
    }
1643
1644
    /**
1645
	 * Get the invoice fees.
1646
	 *
1647
	 * @since 1.0.19
1648
	 * @param  string $context View or edit context.
1649
	 * @return array
1650
	 */
1651
	public function get_fees( $context = 'view' ) {
1652
		return wpinv_parse_list( $this->get_prop( 'fees', $context ) );
1653
    }
1654
1655
    /**
1656
	 * Get the invoice discounts.
1657
	 *
1658
	 * @since 1.0.19
1659
	 * @param  string $context View or edit context.
1660
	 * @return array
1661
	 */
1662
	public function get_discounts( $context = 'view' ) {
1663
		return wpinv_parse_list( $this->get_prop( 'discounts', $context ) );
1664
    }
1665
1666
    /**
1667
	 * Get the invoice taxes.
1668
	 *
1669
	 * @since 1.0.19
1670
	 * @param  string $context View or edit context.
1671
	 * @return array
1672
	 */
1673
	public function get_taxes( $context = 'view' ) {
1674
		return wpinv_parse_list( $this->get_prop( 'taxes', $context ) );
1675
    }
1676
1677
    /**
1678
	 * Get the invoice items.
1679
	 *
1680
	 * @since 1.0.19
1681
	 * @param  string $context View or edit context.
1682
	 * @return GetPaid_Form_Item[]
1683
	 */
1684
	public function get_items( $context = 'view' ) {
1685
        return $this->get_prop( 'items', $context );
1686
	}
1687
1688
	/**
1689
	 * Get the invoice item ids.
1690
	 *
1691
	 * @since 1.0.19
1692
	 * @return string
1693
	 */
1694
	public function get_item_ids() {
1695
		return implode( ', ', wp_list_pluck( $this->get_cart_details(), 'item_id' ) );
1696
    }
1697
1698
    /**
1699
	 * Get the invoice's payment form.
1700
	 *
1701
	 * @since 1.0.19
1702
	 * @param  string $context View or edit context.
1703
	 * @return int
1704
	 */
1705
	public function get_payment_form( $context = 'view' ) {
1706
		return intval( $this->get_prop( 'payment_form', $context ) );
1707
    }
1708
1709
    /**
1710
	 * Get the invoice's submission id.
1711
	 *
1712
	 * @since 1.0.19
1713
	 * @param  string $context View or edit context.
1714
	 * @return string
1715
	 */
1716
	public function get_submission_id( $context = 'view' ) {
1717
		return $this->get_prop( 'submission_id', $context );
1718
    }
1719
1720
    /**
1721
	 * Get the invoice's discount code.
1722
	 *
1723
	 * @since 1.0.19
1724
	 * @param  string $context View or edit context.
1725
	 * @return string
1726
	 */
1727
	public function get_discount_code( $context = 'view' ) {
1728
		return $this->get_prop( 'discount_code', $context );
1729
    }
1730
1731
    /**
1732
	 * Get the invoice's gateway.
1733
	 *
1734
	 * @since 1.0.19
1735
	 * @param  string $context View or edit context.
1736
	 * @return string
1737
	 */
1738
	public function get_gateway( $context = 'view' ) {
1739
		return $this->get_prop( 'gateway', $context );
1740
    }
1741
1742
    /**
1743
	 * Get the invoice's gateway display title.
1744
	 *
1745
	 * @since 1.0.19
1746
	 * @return string
1747
	 */
1748
    public function get_gateway_title() {
1749
        $title = wpinv_get_gateway_checkout_label( $this->get_gateway() );
1750
        return apply_filters( 'wpinv_gateway_title', $title, $this->get_id(), $this );
1751
    }
1752
1753
    /**
1754
	 * Get the invoice's transaction id.
1755
	 *
1756
	 * @since 1.0.19
1757
	 * @param  string $context View or edit context.
1758
	 * @return string
1759
	 */
1760
	public function get_transaction_id( $context = 'view' ) {
1761
		return $this->get_prop( 'transaction_id', $context );
1762
    }
1763
1764
    /**
1765
	 * Get the invoice's currency.
1766
	 *
1767
	 * @since 1.0.19
1768
	 * @param  string $context View or edit context.
1769
	 * @return string
1770
	 */
1771
	public function get_currency( $context = 'view' ) {
1772
        $currency = $this->get_prop( 'currency', $context );
1773
        return empty( $currency ) ? wpinv_get_currency() : $currency;
1774
    }
1775
1776
    /**
1777
	 * Checks if we are charging taxes for this invoice.
1778
	 *
1779
	 * @since 1.0.19
1780
	 * @param  string $context View or edit context.
1781
	 * @return bool
1782
	 */
1783
	public function get_disable_taxes( $context = 'view' ) {
1784
        return (bool) $this->get_prop( 'disable_taxes', $context );
1785
    }
1786
1787
    /**
1788
	 * Retrieves the subscription id for an invoice.
1789
	 *
1790
	 * @since 1.0.19
1791
	 * @param  string $context View or edit context.
1792
	 * @return int
1793
	 */
1794
    public function get_subscription_id( $context = 'view' ) {
1795
		return $this->is_renewal() ? $this->get_parent()->get_subscription_id( $context ) : $this->get_prop( 'subscription_id', $context );
1796
	}
1797
1798
	/**
1799
	 * Retrieves the remote subscription id for an invoice.
1800
	 *
1801
	 * @since 1.0.19
1802
	 * @param  string $context View or edit context.
1803
	 * @return int
1804
	 */
1805
    public function get_remote_subscription_id( $context = 'view' ) {
1806
        $subscription_id = $this->get_prop( 'remote_subscription_id', $context );
1807
1808
        if ( empty( $subscription_id ) && $this->is_renewal() ) {
1809
            $parent = $this->get_parent();
1810
            return $parent->get_remote_subscription_id( $context );
1811
        }
1812
1813
        return $subscription_id;
1814
    }
1815
1816
	/**
1817
	 * Get the invoice's _anonymize status.
1818
	 *
1819
	 * @since 2.8.22
1820
	 * @param  string $context View or edit context.
1821
	 * @return string
1822
	 */
1823
	public function get_is_anonymized( $context = 'view' ) {
1824
		return (bool) $this->get_prop( 'is_anonymized', $context );
1825
    }
1826
1827
    /**
1828
	 * Retrieves the payment meta for an invoice.
1829
	 *
1830
	 * @since 1.0.19
1831
	 * @param  string $context View or edit context.
1832
	 * @return array
1833
	 */
1834
    public function get_payment_meta( $context = 'view' ) {
1835
1836
        return array(
1837
            'price'        => $this->get_total( $context ),
1838
            'date'         => $this->get_date_created( $context ),
1839
            'user_email'   => $this->get_email( $context ),
1840
            'invoice_key'  => $this->get_key( $context ),
1841
            'currency'     => $this->get_currency( $context ),
1842
            'items'        => $this->get_items( $context ),
1843
            'user_info'    => $this->get_user_info( $context ),
1844
            'cart_details' => $this->get_cart_details(),
1845
            'status'       => $this->get_status( $context ),
1846
            'fees'         => $this->get_fees( $context ),
1847
            'taxes'        => $this->get_taxes( $context ),
1848
        );
1849
1850
    }
1851
1852
    /**
1853
	 * Retrieves the cart details for an invoice.
1854
	 *
1855
	 * @since 1.0.19
1856
	 * @return array
1857
	 */
1858
    public function get_cart_details() {
1859
        $items        = $this->get_items();
1860
        $cart_details = array();
1861
1862
        foreach ( $items as $item ) {
1863
			$item->invoice_id = $this->get_id();
1864
            $cart_details[]   = $item->prepare_data_for_saving();
1865
        }
1866
1867
        return $cart_details;
1868
	}
1869
1870
	/**
1871
	 * Retrieves the recurring item.
1872
	 *
1873
	 * @return null|GetPaid_Form_Item|int
1874
	 */
1875
	public function get_recurring( $object = false ) {
1876
1877
		// Are we returning an object?
1878
        if ( $object ) {
1879
            return $this->get_item( $this->recurring_item );
1880
        }
1881
1882
        return $this->recurring_item;
1883
    }
1884
1885
	/**
1886
	 * Retrieves the subscription name.
1887
	 *
1888
	 * @since 1.0.19
1889
	 * @return string
1890
	 */
1891
	public function get_subscription_name() {
1892
1893
		// Retrieve the recurring name
1894
        $item = $this->get_recurring( true );
1895
1896
		// Abort if it does not exist.
1897
        if ( empty( $item ) ) {
1898
            return '';
1899
        }
1900
1901
		// Return the item name.
1902
        return apply_filters( 'wpinv_invoice_get_subscription_name', $item->get_name(), $this );
1903
	}
1904
1905
	/**
1906
	 * Retrieves the view url.
1907
	 *
1908
	 * @since 1.0.19
1909
	 * @return string
1910
	 */
1911
	public function get_view_url() {
1912
        $invoice_url = get_permalink( $this->get_id() );
1913
		$invoice_url = add_query_arg( 'invoice_key', $this->get_key(), $invoice_url );
1914
        return apply_filters( 'wpinv_get_view_url', $invoice_url, $this );
1915
	}
1916
1917
	/**
1918
	 * Retrieves the payment url.
1919
	 *
1920
	 * @since 1.0.19
1921
	 * @return string
1922
	 */
1923
	public function get_checkout_payment_url( $deprecated = false, $secret = false ) {
1924
1925
		// Retrieve the checkout url.
1926
        $pay_url = wpinv_get_checkout_uri();
1927
1928
		// Maybe force ssl.
1929
        if ( is_ssl() ) {
1930
            $pay_url = str_replace( 'http:', 'https:', $pay_url );
1931
        }
1932
1933
		// Add the invoice key.
1934
		$pay_url = add_query_arg( 'invoice_key', $this->get_key(), $pay_url );
1935
1936
		// (Maybe?) add a secret
1937
        if ( $secret ) {
1938
            $pay_url = add_query_arg( array( '_wpipay' => md5( $this->get_user_id() . '::' . $this->get_email() . '::' . $this->get_key() ) ), $pay_url );
1939
        }
1940
1941
        return apply_filters( 'wpinv_get_checkout_payment_url', $pay_url, $this, $deprecated, $secret );
1942
	}
1943
1944
	/**
1945
	 * Retrieves the receipt url.
1946
	 *
1947
	 * @since 1.0.19
1948
	 * @return string
1949
	 */
1950
	public function get_receipt_url() {
1951
1952
		// Retrieve the checkout url.
1953
        $receipt_url = wpinv_get_success_page_uri();
1954
1955
		// Maybe force ssl.
1956
        if ( is_ssl() ) {
1957
            $receipt_url = str_replace( 'http:', 'https:', $receipt_url );
1958
        }
1959
1960
		// Add the invoice key.
1961
		$receipt_url = add_query_arg( 'invoice_key', $this->get_key(), $receipt_url );
1962
1963
        return apply_filters( 'getpaid_get_invoice_receipt_url', $receipt_url, $this );
1964
	}
1965
1966
	/**
1967
	 * Retrieves the remote transaction url.
1968
	 *
1969
	 * @since 1.6.0
1970
	 * @return string
1971
	 */
1972
	public function get_transaction_url() {
1973
		return apply_filters( 'getpaid_gateway_' . $this->get_gateway() . '_transaction_url', '', $this );
1974
	}
1975
1976
	/**
1977
	 * Retrieves the default status.
1978
	 *
1979
	 * @since 1.0.19
1980
	 * @return string
1981
	 */
1982
	public function get_default_status() {
1983
1984
		$type   = $this->get_type();
1985
		$status = "wpi-$type-pending";
1986
		return str_replace( '-invoice', '', $status );
1987
1988
	}
1989
1990
    /**
1991
	 * Magic method for accessing invoice properties.
1992
	 *
1993
	 * @since 1.0.15
1994
	 * @access public
1995
	 *
1996
	 * @param string $key Discount data to retrieve
1997
	 * @param  string $context View or edit context.
1998
	 * @return mixed Value of the given invoice property (if set).
1999
	 */
2000
	public function get( $key, $context = 'view' ) {
2001
		$method = "get_$key";
2002
2003
		if ( is_callable( array( $this, $method ) ) ) {
2004
			return $this->$method( $context );
2005
		}
2006
2007
        return $this->get_prop( $key, $context );
2008
	}
2009
2010
    /*
2011
	|--------------------------------------------------------------------------
2012
	| Setters
2013
	|--------------------------------------------------------------------------
2014
	|
2015
	| Functions for setting item data. These should not update anything in the
2016
	| database itself and should only change what is stored in the class
2017
	| object.
2018
    */
2019
2020
    /**
2021
	 * Magic method for setting invoice properties.
2022
	 *
2023
	 * @since 1.0.19
2024
	 * @access public
2025
	 *
2026
	 * @param string $key Discount data to retrieve
2027
	 * @param  mixed $value new value.
2028
	 * @return mixed Value of the given invoice property (if set).
2029
	 */
2030
	public function set( $key, $value ) {
2031
2032
        $setter = "set_$key";
2033
        if ( is_callable( array( $this, $setter ) ) ) {
2034
            $this->{$setter}( $value );
2035
        }
2036
2037
	}
2038
2039
	/**
2040
	 * Sets item status.
2041
	 *
2042
	 * @since 1.0.19
2043
	 * @param string $new_status    New status.
2044
	 * @param string $note          Optional note to add.
2045
	 * @param bool   $manual_update Is this a manual status change?.
2046
	 * @return array details of change.
2047
	 */
2048
	public function set_status( $new_status, $note = '', $manual_update = false ) {
2049
		$old_status = $this->get_status();
2050
2051
		$statuses = $this->get_all_statuses();
2052
2053
		if ( isset( $statuses['draft'] ) ) {
2054
			unset( $statuses['draft'] );
2055
		}
2056
2057
		$this->set_prop( 'status', $new_status );
2058
2059
		// If setting the status, ensure it's set to a valid status.
2060
		if ( true === $this->object_read ) {
2061
2062
			// Only allow valid new status.
2063
			if ( ! array_key_exists( $new_status, $statuses ) ) {
2064
				$new_status = $this->get_default_status();
2065
			}
2066
2067
			// If the old status is set but unknown (e.g. draft) assume its pending for action usage.
2068
			if ( $old_status && ! array_key_exists( $new_status, $statuses ) ) {
2069
				$old_status = $this->get_default_status();
2070
			}
2071
2072
			// Paid - Renewal (i.e when duplicating a parent invoice )
2073
			if ( $new_status == 'wpi-pending' && $old_status == 'publish' && ! $this->get_id() ) {
2074
				$old_status = 'wpi-pending';
2075
			}
2076
2077
			if ( $old_status !== $new_status ) {
2078
				$this->status_transition = array(
2079
					'from'   => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $old_status,
2080
					'to'     => $new_status,
2081
					'note'   => $note,
2082
					'manual' => (bool) $manual_update,
2083
				);
2084
2085
				if ( $manual_update ) {
2086
					do_action( 'getpaid_' . $this->object_type . '_edit_status', $this->get_id(), $new_status );
2087
				}
2088
2089
				$this->maybe_set_date_paid();
2090
2091
			}
2092
		}
2093
2094
		return array(
2095
			'from' => $old_status,
2096
			'to'   => $new_status,
2097
		);
2098
	}
2099
2100
	/**
2101
	 * Maybe set date paid.
2102
	 *
2103
	 * Sets the date paid variable when transitioning to the payment complete
2104
	 * order status.
2105
	 *
2106
	 * @since 1.0.19
2107
	 */
2108
	public function maybe_set_date_paid() {
2109
2110
		if ( ! $this->get_date_completed( 'edit' ) && $this->is_paid() ) {
2111
			$this->set_date_completed( current_time( 'mysql' ) );
2112
		}
2113
	}
2114
2115
    /**
2116
	 * Set parent invoice ID.
2117
	 *
2118
	 * @since 1.0.19
2119
	 */
2120
	public function set_parent_id( $value ) {
2121
		if ( $value && ( $value === $this->get_id() ) ) {
2122
			return;
2123
		}
2124
		$this->set_prop( 'parent_id', absint( $value ) );
2125
    }
2126
2127
    /**
2128
	 * Set plugin version when the invoice was created.
2129
	 *
2130
	 * @since 1.0.19
2131
	 */
2132
	public function set_version( $value ) {
2133
		$this->set_prop( 'version', $value );
2134
    }
2135
2136
    /**
2137
	 * Set date when the invoice was created.
2138
	 *
2139
	 * @since 1.0.19
2140
	 * @param string $value Value to set.
2141
     * @return bool Whether or not the date was set.
2142
	 */
2143
	public function set_date_created( $value ) {
2144
        $date = strtotime( $value );
2145
2146
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
2147
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
2148
            return true;
2149
        }
2150
2151
		$this->set_prop( 'date_created', '' );
2152
		return false;
2153
2154
    }
2155
2156
    /**
2157
	 * Set date invoice due date.
2158
	 *
2159
	 * @since 1.0.19
2160
	 * @param string $value Value to set.
2161
     * @return bool Whether or not the date was set.
2162
	 */
2163
	public function set_due_date( $value ) {
2164
        $date = strtotime( $value );
2165
2166
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
2167
            $this->set_prop( 'due_date', date( 'Y-m-d H:i:s', $date ) );
2168
            return true;
2169
        }
2170
2171
		$this->set_prop( 'due_date', '' );
2172
        return false;
2173
2174
    }
2175
2176
    /**
2177
	 * Alias of self::set_due_date().
2178
	 *
2179
	 * @since 1.0.19
2180
	 * @param  string $value New name.
2181
	 */
2182
	public function set_date_due( $value ) {
2183
		$this->set_due_date( $value );
2184
    }
2185
2186
    /**
2187
	 * Set date invoice was completed.
2188
	 *
2189
	 * @since 1.0.19
2190
	 * @param string $value Value to set.
2191
     * @return bool Whether or not the date was set.
2192
	 */
2193
	public function set_completed_date( $value ) {
2194
        $date = strtotime( $value );
2195
2196
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
2197
            $this->set_prop( 'completed_date', date( 'Y-m-d H:i:s', $date ) );
2198
            return true;
2199
        }
2200
2201
		$this->set_prop( 'completed_date', '' );
2202
        return false;
2203
2204
    }
2205
2206
    /**
2207
	 * Alias of self::set_completed_date().
2208
	 *
2209
	 * @since 1.0.19
2210
	 * @param  string $value New name.
2211
	 */
2212
	public function set_date_completed( $value ) {
2213
		$this->set_completed_date( $value );
2214
    }
2215
2216
    /**
2217
	 * Set date when the invoice was last modified.
2218
	 *
2219
	 * @since 1.0.19
2220
	 * @param string $value Value to set.
2221
     * @return bool Whether or not the date was set.
2222
	 */
2223
	public function set_date_modified( $value ) {
2224
        $date = strtotime( $value );
2225
2226
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
2227
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
2228
            return true;
2229
        }
2230
2231
		$this->set_prop( 'date_modified', '' );
2232
        return false;
2233
2234
    }
2235
2236
    /**
2237
	 * Set the invoice number.
2238
	 *
2239
	 * @since 1.0.19
2240
	 * @param  string $value New number.
2241
	 */
2242
	public function set_number( $value ) {
2243
        $number = sanitize_text_field( $value );
2244
		$this->set_prop( 'number', $number );
2245
    }
2246
2247
    /**
2248
	 * Set the invoice type.
2249
	 *
2250
	 * @since 1.0.19
2251
	 * @param  string $value Type.
2252
	 */
2253
	public function set_type( $value ) {
2254
        $type = sanitize_text_field( str_replace( 'wpi_', '', $value ) );
2255
		$this->set_prop( 'type', $type );
2256
	}
2257
2258
    /**
2259
	 * Set the invoice post type.
2260
	 *
2261
	 * @since 1.0.19
2262
	 * @param  string $value Post type.
2263
	 */
2264
	public function set_post_type( $value ) {
2265
        if ( getpaid_is_invoice_post_type( $value ) ) {
2266
			$this->set_type( $value );
2267
            $this->set_prop( 'post_type', $value );
2268
        }
2269
    }
2270
2271
    /**
2272
	 * Set the invoice key.
2273
	 *
2274
	 * @since 1.0.19
2275
	 * @param  string $value New key.
2276
	 */
2277
	public function set_key( $value ) {
2278
        $key = sanitize_text_field( $value );
2279
		$this->set_prop( 'key', $key );
2280
    }
2281
2282
    /**
2283
	 * Set the invoice mode.
2284
	 *
2285
	 * @since 1.0.19
2286
	 * @param  string $value mode.
2287
	 */
2288
	public function set_mode( $value ) {
2289
        if ( in_array( $value, array( 'live', 'test' ) ) ) {
2290
            $this->set_prop( 'mode', $value );
2291
        }
2292
    }
2293
2294
    /**
2295
	 * Set the invoice path.
2296
	 *
2297
	 * @since 1.0.19
2298
	 * @param  string $value path.
2299
	 */
2300
	public function set_path( $value ) {
2301
        $this->set_prop( 'path', $value );
2302
    }
2303
2304
    /**
2305
	 * Set the invoice name.
2306
	 *
2307
	 * @since 1.0.19
2308
	 * @param  string $value New name.
2309
	 */
2310
	public function set_name( $value ) {
2311
        $name = sanitize_text_field( $value );
2312
		$this->set_prop( 'name', $name );
2313
    }
2314
2315
    /**
2316
	 * Alias of self::set_name().
2317
	 *
2318
	 * @since 1.0.19
2319
	 * @param  string $value New name.
2320
	 */
2321
	public function set_title( $value ) {
2322
		$this->set_name( $value );
2323
    }
2324
2325
    /**
2326
	 * Set the invoice description.
2327
	 *
2328
	 * @since 1.0.19
2329
	 * @param  string $value New description.
2330
	 */
2331
	public function set_description( $value ) {
2332
        $description = wp_kses_post( $value );
2333
		$this->set_prop( 'description', $description );
2334
    }
2335
2336
    /**
2337
	 * Alias of self::set_description().
2338
	 *
2339
	 * @since 1.0.19
2340
	 * @param  string $value New description.
2341
	 */
2342
	public function set_excerpt( $value ) {
2343
		$this->set_description( $value );
2344
    }
2345
2346
    /**
2347
	 * Alias of self::set_description().
2348
	 *
2349
	 * @since 1.0.19
2350
	 * @param  string $value New description.
2351
	 */
2352
	public function set_summary( $value ) {
2353
		$this->set_description( $value );
2354
    }
2355
2356
    /**
2357
	 * Set the receiver of the invoice.
2358
	 *
2359
	 * @since 1.0.19
2360
	 * @param  int $value New author.
2361
	 */
2362
	public function set_author( $value ) {
2363
		$user = get_user_by( 'id', (int) $value );
2364
2365
		if ( $user && $user->ID ) {
2366
			$this->set_prop( 'author', $user->ID );
2367
			$this->set_prop( 'email', $user->user_email );
2368
		}
2369
2370
    }
2371
2372
    /**
2373
	 * Alias of self::set_author().
2374
	 *
2375
	 * @since 1.0.19
2376
	 * @param  int $value New user id.
2377
	 */
2378
	public function set_user_id( $value ) {
2379
		$this->set_author( $value );
2380
    }
2381
2382
    /**
2383
	 * Sets the customer ID.
2384
	 *
2385
	 * @since 1.0.19
2386
	 * @param  int $value New user id.
2387
	 */
2388
	public function set_customer_id( $value ) {
2389
		$this->set_prop( 'customer_id', (int) $value );
2390
    }
2391
2392
    /**
2393
	 * Set the customer's ip.
2394
	 *
2395
	 * @since 1.0.19
2396
	 * @param  string $value ip address.
2397
	 */
2398
	public function set_ip( $value ) {
2399
		$this->set_prop( 'ip', $value );
2400
    }
2401
2402
    /**
2403
	 * Alias of self::set_ip().
2404
	 *
2405
	 * @since 1.0.19
2406
	 * @param  string $value ip address.
2407
	 */
2408
	public function set_user_ip( $value ) {
2409
		$this->set_ip( $value );
2410
    }
2411
2412
    /**
2413
	 * Set the customer's first name.
2414
	 *
2415
	 * @since 1.0.19
2416
	 * @param  string $value first name.
2417
	 */
2418
	public function set_first_name( $value ) {
2419
		$this->set_prop( 'first_name', $value );
2420
    }
2421
2422
    /**
2423
	 * Alias of self::set_first_name().
2424
	 *
2425
	 * @since 1.0.19
2426
	 * @param  string $value first name.
2427
	 */
2428
	public function set_user_first_name( $value ) {
2429
		$this->set_first_name( $value );
2430
    }
2431
2432
    /**
2433
	 * Alias of self::set_first_name().
2434
	 *
2435
	 * @since 1.0.19
2436
	 * @param  string $value first name.
2437
	 */
2438
	public function set_customer_first_name( $value ) {
2439
		$this->set_first_name( $value );
2440
    }
2441
2442
    /**
2443
	 * Set the customer's last name.
2444
	 *
2445
	 * @since 1.0.19
2446
	 * @param  string $value last name.
2447
	 */
2448
	public function set_last_name( $value ) {
2449
		$this->set_prop( 'last_name', $value );
2450
    }
2451
2452
    /**
2453
	 * Alias of self::set_last_name().
2454
	 *
2455
	 * @since 1.0.19
2456
	 * @param  string $value last name.
2457
	 */
2458
	public function set_user_last_name( $value ) {
2459
		$this->set_last_name( $value );
2460
    }
2461
2462
    /**
2463
	 * Alias of self::set_last_name().
2464
	 *
2465
	 * @since 1.0.19
2466
	 * @param  string $value last name.
2467
	 */
2468
	public function set_customer_last_name( $value ) {
2469
		$this->set_last_name( $value );
2470
    }
2471
2472
    /**
2473
	 * Set the customer's phone number.
2474
	 *
2475
	 * @since 1.0.19
2476
	 * @param  string $value phone.
2477
	 */
2478
	public function set_phone( $value ) {
2479
		$this->set_prop( 'phone', $value );
2480
    }
2481
2482
    /**
2483
	 * Alias of self::set_phone().
2484
	 *
2485
	 * @since 1.0.19
2486
	 * @param  string $value phone.
2487
	 */
2488
	public function set_user_phone( $value ) {
2489
		$this->set_phone( $value );
2490
    }
2491
2492
    /**
2493
	 * Alias of self::set_phone().
2494
	 *
2495
	 * @since 1.0.19
2496
	 * @param  string $value phone.
2497
	 */
2498
	public function set_customer_phone( $value ) {
2499
		$this->set_phone( $value );
2500
    }
2501
2502
    /**
2503
	 * Alias of self::set_phone().
2504
	 *
2505
	 * @since 1.0.19
2506
	 * @param  string $value phone.
2507
	 */
2508
	public function set_phone_number( $value ) {
2509
		$this->set_phone( $value );
2510
    }
2511
2512
    /**
2513
	 * Set the customer's email address.
2514
	 *
2515
	 * @since 1.0.19
2516
	 * @param  string $value email address.
2517
	 */
2518
	public function set_email( $value ) {
2519
		$this->set_prop( 'email', $value );
2520
    }
2521
2522
    /**
2523
	 * Alias of self::set_email().
2524
	 *
2525
	 * @since 1.0.19
2526
	 * @param  string $value email address.
2527
	 */
2528
	public function set_user_email( $value ) {
2529
		$this->set_email( $value );
2530
    }
2531
2532
    /**
2533
	 * Alias of self::set_email().
2534
	 *
2535
	 * @since 1.0.19
2536
	 * @param  string $value email address.
2537
	 */
2538
	public function set_email_address( $value ) {
2539
		$this->set_email( $value );
2540
    }
2541
2542
    /**
2543
	 * Alias of self::set_email().
2544
	 *
2545
	 * @since 1.0.19
2546
	 * @param  string $value email address.
2547
	 */
2548
	public function set_customer_email( $value ) {
2549
		$this->set_email( $value );
2550
    }
2551
2552
    /**
2553
	 * Set the customer's country.
2554
	 *
2555
	 * @since 1.0.19
2556
	 * @param  string $value country.
2557
	 */
2558
	public function set_country( $value ) {
2559
		$this->set_prop( 'country', $value );
2560
    }
2561
2562
    /**
2563
	 * Alias of self::set_country().
2564
	 *
2565
	 * @since 1.0.19
2566
	 * @param  string $value country.
2567
	 */
2568
	public function set_user_country( $value ) {
2569
		$this->set_country( $value );
2570
    }
2571
2572
    /**
2573
	 * Alias of self::set_country().
2574
	 *
2575
	 * @since 1.0.19
2576
	 * @param  string $value country.
2577
	 */
2578
	public function set_customer_country( $value ) {
2579
		$this->set_country( $value );
2580
    }
2581
2582
    /**
2583
	 * Set the customer's state.
2584
	 *
2585
	 * @since 1.0.19
2586
	 * @param  string $value state.
2587
	 */
2588
	public function set_state( $value ) {
2589
		$this->set_prop( 'state', $value );
2590
    }
2591
2592
    /**
2593
	 * Alias of self::set_state().
2594
	 *
2595
	 * @since 1.0.19
2596
	 * @param  string $value state.
2597
	 */
2598
	public function set_user_state( $value ) {
2599
		$this->set_state( $value );
2600
    }
2601
2602
    /**
2603
	 * Alias of self::set_state().
2604
	 *
2605
	 * @since 1.0.19
2606
	 * @param  string $value state.
2607
	 */
2608
	public function set_customer_state( $value ) {
2609
		$this->set_state( $value );
2610
    }
2611
2612
    /**
2613
	 * Set the customer's city.
2614
	 *
2615
	 * @since 1.0.19
2616
	 * @param  string $value city.
2617
	 */
2618
	public function set_city( $value ) {
2619
		$this->set_prop( 'city', $value );
2620
    }
2621
2622
    /**
2623
	 * Alias of self::set_city().
2624
	 *
2625
	 * @since 1.0.19
2626
	 * @param  string $value city.
2627
	 */
2628
	public function set_user_city( $value ) {
2629
		$this->set_city( $value );
2630
    }
2631
2632
    /**
2633
	 * Alias of self::set_city().
2634
	 *
2635
	 * @since 1.0.19
2636
	 * @param  string $value city.
2637
	 */
2638
	public function set_customer_city( $value ) {
2639
		$this->set_city( $value );
2640
    }
2641
2642
    /**
2643
	 * Set the customer's zip code.
2644
	 *
2645
	 * @since 1.0.19
2646
	 * @param  string $value zip.
2647
	 */
2648
	public function set_zip( $value ) {
2649
		$this->set_prop( 'zip', $value );
2650
    }
2651
2652
    /**
2653
	 * Alias of self::set_zip().
2654
	 *
2655
	 * @since 1.0.19
2656
	 * @param  string $value zip.
2657
	 */
2658
	public function set_user_zip( $value ) {
2659
		$this->set_zip( $value );
2660
    }
2661
2662
    /**
2663
	 * Alias of self::set_zip().
2664
	 *
2665
	 * @since 1.0.19
2666
	 * @param  string $value zip.
2667
	 */
2668
	public function set_customer_zip( $value ) {
2669
		$this->set_zip( $value );
2670
    }
2671
2672
    /**
2673
	 * Set the customer's company.
2674
	 *
2675
	 * @since 1.0.19
2676
	 * @param  string $value company.
2677
	 */
2678
	public function set_company( $value ) {
2679
		$this->set_prop( 'company', $value );
2680
    }
2681
2682
    /**
2683
	 * Alias of self::set_company().
2684
	 *
2685
	 * @since 1.0.19
2686
	 * @param  string $value company.
2687
	 */
2688
	public function set_user_company( $value ) {
2689
		$this->set_company( $value );
2690
    }
2691
2692
    /**
2693
	 * Alias of self::set_company().
2694
	 *
2695
	 * @since 1.0.19
2696
	 * @param  string $value company.
2697
	 */
2698
	public function set_customer_company( $value ) {
2699
		$this->set_company( $value );
2700
    }
2701
2702
	/**
2703
	 * Set the customer's company id.
2704
	 *
2705
	 * @since 1.0.19
2706
	 * @param  string $value company id.
2707
	 */
2708
	public function set_company_id( $value ) {
2709
		$this->set_prop( 'company_id', $value );
2710
    }
2711
2712
    /**
2713
	 * Set the customer's var number.
2714
	 *
2715
	 * @since 1.0.19
2716
	 * @param  string $value var number.
2717
	 */
2718
	public function set_vat_number( $value ) {
2719
		$this->set_prop( 'vat_number', $value );
2720
    }
2721
2722
    /**
2723
	 * Alias of self::set_vat_number().
2724
	 *
2725
	 * @since 1.0.19
2726
	 * @param  string $value var number.
2727
	 */
2728
	public function set_user_vat_number( $value ) {
2729
		$this->set_vat_number( $value );
2730
    }
2731
2732
    /**
2733
	 * Alias of self::set_vat_number().
2734
	 *
2735
	 * @since 1.0.19
2736
	 * @param  string $value var number.
2737
	 */
2738
	public function set_customer_vat_number( $value ) {
2739
		$this->set_vat_number( $value );
2740
    }
2741
2742
    /**
2743
	 * Set the customer's vat rate.
2744
	 *
2745
	 * @since 1.0.19
2746
	 * @param  string $value var rate.
2747
	 */
2748
	public function set_vat_rate( $value ) {
2749
		$this->set_prop( 'vat_rate', $value );
2750
    }
2751
2752
    /**
2753
	 * Alias of self::set_vat_rate().
2754
	 *
2755
	 * @since 1.0.19
2756
	 * @param  string $value var number.
2757
	 */
2758
	public function set_user_vat_rate( $value ) {
2759
		$this->set_vat_rate( $value );
2760
    }
2761
2762
    /**
2763
	 * Alias of self::set_vat_rate().
2764
	 *
2765
	 * @since 1.0.19
2766
	 * @param  string $value var number.
2767
	 */
2768
	public function set_customer_vat_rate( $value ) {
2769
		$this->set_vat_rate( $value );
2770
    }
2771
2772
    /**
2773
	 * Set the customer's address.
2774
	 *
2775
	 * @since 1.0.19
2776
	 * @param  string $value address.
2777
	 */
2778
	public function set_address( $value ) {
2779
		$this->set_prop( 'address', $value );
2780
    }
2781
2782
    /**
2783
	 * Alias of self::set_address().
2784
	 *
2785
	 * @since 1.0.19
2786
	 * @param  string $value address.
2787
	 */
2788
	public function set_user_address( $value ) {
2789
		$this->set_address( $value );
2790
    }
2791
2792
    /**
2793
	 * Alias of self::set_address().
2794
	 *
2795
	 * @since 1.0.19
2796
	 * @param  string $value address.
2797
	 */
2798
	public function set_customer_address( $value ) {
2799
		$this->set_address( $value );
2800
    }
2801
2802
    /**
2803
	 * Set whether the customer has viewed the invoice or not.
2804
	 *
2805
	 * @since 1.0.19
2806
	 * @param  int|bool $value confirmed.
2807
	 */
2808
	public function set_is_viewed( $value ) {
2809
		$this->set_prop( 'is_viewed', $value );
2810
	}
2811
2812
	/**
2813
	 * Set extra email recipients.
2814
	 *
2815
	 * @since 1.0.19
2816
	 * @param  string $value email recipients.
2817
	 */
2818
	public function set_email_cc( $value ) {
2819
		$this->set_prop( 'email_cc', $value );
2820
	}
2821
2822
	/**
2823
	 * Set the invoice template.
2824
	 *
2825
	 * @since 1.0.19
2826
	 * @param  string $value template.
2827
	 */
2828
	public function set_template( $value ) {
2829
		if ( in_array( $value, array( 'quantity', 'hours', 'amount' ) ) ) {
2830
			$this->set_prop( 'template', $value );
2831
		}
2832
	}
2833
2834
	/**
2835
	 * Set the invoice source.
2836
	 *
2837
	 * @since 1.0.19
2838
	 * @param  string $value source.
2839
	 * @deprecated
2840
	 */
2841
	public function created_via( $value ) {
2842
		$this->set_created_via( sanitize_text_field( $value ) );
2843
	}
2844
2845
	/**
2846
	 * Set the invoice source.
2847
	 *
2848
	 * @since 1.0.19
2849
	 * @param  string $value source.
2850
	 */
2851
	public function set_created_via( $value ) {
2852
		$this->set_prop( 'created_via', sanitize_text_field( $value ) );
2853
	}
2854
2855
	/**
2856
	 * Set the customer's address confirmed status.
2857
	 *
2858
	 * @since 1.0.19
2859
	 * @param  int|bool $value confirmed.
2860
	 */
2861
	public function set_address_confirmed( $value ) {
2862
		$this->set_prop( 'address_confirmed', $value );
2863
    }
2864
2865
    /**
2866
	 * Alias of self::set_address_confirmed().
2867
	 *
2868
	 * @since 1.0.19
2869
	 * @param  int|bool $value confirmed.
2870
	 */
2871
	public function set_user_address_confirmed( $value ) {
2872
		$this->set_address_confirmed( $value );
2873
    }
2874
2875
    /**
2876
	 * Alias of self::set_address_confirmed().
2877
	 *
2878
	 * @since 1.0.19
2879
	 * @param  int|bool $value confirmed.
2880
	 */
2881
	public function set_customer_address_confirmed( $value ) {
2882
		$this->set_address_confirmed( $value );
2883
    }
2884
2885
    /**
2886
	 * Set the shipping fee
2887
	 *
2888
	 * @since 1.0.19
2889
	 * @param  float $value shipping amount.
2890
	 */
2891
	public function set_shipping( $value ) {
2892
2893
		if ( ! is_numeric( $value ) ) {
2894
			return $this->set_prop( 'shipping', null );
2895
		}
2896
2897
		$this->set_prop( 'shipping', max( 0, floatval( $value ) ) );
2898
	}
2899
2900
	/**
2901
	 * Set the invoice sub total.
2902
	 *
2903
	 * @since 1.0.19
2904
	 * @param  float $value sub total.
2905
	 */
2906
	public function set_subtotal( $value ) {
2907
		$this->set_prop( 'subtotal', max( 0, $value ) );
2908
	}
2909
2910
	/**
2911
	 * Set the invoice total.
2912
	 *
2913
	 * @since 1.0.19
2914
	 * @param  float $value sub total.
2915
	 */
2916
	public function set_total( $value ) {
2917
		$this->set_prop( 'total', max( 0, $value ) );
2918
    }
2919
2920
    /**
2921
	 * Set the invoice discount amount.
2922
	 *
2923
	 * @since 1.0.19
2924
	 * @param  float $value discount total.
2925
	 */
2926
	public function set_total_discount( $value ) {
2927
		$this->set_prop( 'total_discount', max( 0, $value ) );
2928
    }
2929
2930
    /**
2931
	 * Alias of self::set_total_discount().
2932
	 *
2933
	 * @since 1.0.19
2934
	 * @param  float $value discount total.
2935
	 */
2936
	public function set_discount( $value ) {
2937
		$this->set_total_discount( $value );
2938
    }
2939
2940
    /**
2941
	 * Set the invoice tax amount.
2942
	 *
2943
	 * @since 1.0.19
2944
	 * @param  float $value tax total.
2945
	 */
2946
	public function set_total_tax( $value ) {
2947
		$this->set_prop( 'total_tax', max( 0, $value ) );
2948
    }
2949
2950
    /**
2951
	 * Alias of self::set_total_tax().
2952
	 *
2953
	 * @since 1.0.19
2954
	 * @param  float $value tax total.
2955
	 */
2956
	public function set_tax_total( $value ) {
2957
		$this->set_total_tax( $value );
2958
    }
2959
2960
    /**
2961
	 * Set the invoice fees amount.
2962
	 *
2963
	 * @since 1.0.19
2964
	 * @param  float $value fees total.
2965
	 */
2966
	public function set_total_fees( $value ) {
2967
		$this->set_prop( 'total_fees', max( 0, $value ) );
2968
    }
2969
2970
    /**
2971
	 * Alias of self::set_total_fees().
2972
	 *
2973
	 * @since 1.0.19
2974
	 * @param  float $value fees total.
2975
	 */
2976
	public function set_fees_total( $value ) {
2977
		$this->set_total_fees( $value );
2978
    }
2979
2980
    /**
2981
	 * Set the invoice fees.
2982
	 *
2983
	 * @since 1.0.19
2984
	 * @param  array $value fees.
2985
	 */
2986
	public function set_fees( $value ) {
2987
2988
		if ( ! is_array( $value ) ) {
2989
			$value = array();
2990
		}
2991
2992
		$this->set_prop( 'fees', $value );
2993
2994
    }
2995
2996
    /**
2997
	 * Set the invoice taxes.
2998
	 *
2999
	 * @since 1.0.19
3000
	 * @param  array $value taxes.
3001
	 */
3002
	public function set_taxes( $value ) {
3003
3004
		if ( ! is_array( $value ) ) {
3005
			$value = array();
3006
		}
3007
3008
		$this->set_prop( 'taxes', $value );
3009
3010
    }
3011
3012
    /**
3013
	 * Set the invoice discounts.
3014
	 *
3015
	 * @since 1.0.19
3016
	 * @param  array $value discounts.
3017
	 */
3018
	public function set_discounts( $value ) {
3019
3020
		if ( ! is_array( $value ) ) {
3021
			$value = array();
3022
		}
3023
3024
		$this->set_prop( 'discounts', $value );
3025
    }
3026
3027
    /**
3028
	 * Set the invoice items.
3029
	 *
3030
	 * @since 1.0.19
3031
	 * @param  GetPaid_Form_Item[] $value items.
3032
	 */
3033
	public function set_items( $value ) {
3034
3035
        // Remove existing items.
3036
        $this->set_prop( 'items', array() );
3037
		$this->recurring_item = null;
3038
3039
        // Ensure that we have an array.
3040
        if ( ! is_array( $value ) ) {
3041
            return;
3042
        }
3043
3044
        foreach ( $value as $item ) {
3045
            $this->add_item( $item );
3046
        }
3047
3048
    }
3049
3050
    /**
3051
	 * Set the payment form.
3052
	 *
3053
	 * @since 1.0.19
3054
	 * @param  int $value payment form.
3055
	 */
3056
	public function set_payment_form( $value ) {
3057
		$this->set_prop( 'payment_form', $value );
3058
    }
3059
3060
    /**
3061
	 * Set the submission id.
3062
	 *
3063
	 * @since 1.0.19
3064
	 * @param  string $value submission id.
3065
	 */
3066
	public function set_submission_id( $value ) {
3067
		$this->set_prop( 'submission_id', $value );
3068
    }
3069
3070
    /**
3071
	 * Set the discount code.
3072
	 *
3073
	 * @since 1.0.19
3074
	 * @param  string $value discount code.
3075
	 */
3076
	public function set_discount_code( $value ) {
3077
		$this->set_prop( 'discount_code', sanitize_text_field( $value ) );
3078
    }
3079
3080
    /**
3081
	 * Set the gateway.
3082
	 *
3083
	 * @since 1.0.19
3084
	 * @param  string $value gateway.
3085
	 */
3086
	public function set_gateway( $value ) {
3087
		$this->set_prop( 'gateway', $value );
3088
    }
3089
3090
    /**
3091
	 * Set the transaction id.
3092
	 *
3093
	 * @since 1.0.19
3094
	 * @param  string $value transaction id.
3095
	 */
3096
	public function set_transaction_id( $value ) {
3097
		if ( ! empty( $value ) ) {
3098
			$this->set_prop( 'transaction_id', $value );
3099
		}
3100
    }
3101
3102
    /**
3103
	 * Set the currency id.
3104
	 *
3105
	 * @since 1.0.19
3106
	 * @param  string $value currency id.
3107
	 */
3108
	public function set_currency( $value ) {
3109
		$this->set_prop( 'currency', $value );
3110
    }
3111
3112
	/**
3113
	 * Set whether to disable taxes.
3114
	 *
3115
	 * @since 1.0.19
3116
	 * @param  bool $value value.
3117
	 */
3118
	public function set_disable_taxes( $value ) {
3119
		$this->set_prop( 'disable_taxes', (bool) $value );
3120
	}
3121
3122
    /**
3123
	 * Set the subscription id.
3124
	 *
3125
	 * @since 1.0.19
3126
	 * @param  string $value subscription id.
3127
	 */
3128
	public function set_subscription_id( $value ) {
3129
		$this->set_prop( 'subscription_id', $value );
3130
	}
3131
3132
	/**
3133
	 * Set the remote subscription id.
3134
	 *
3135
	 * @since 1.0.19
3136
	 * @param  string $value subscription id.
3137
	 */
3138
	public function set_remote_subscription_id( $value ) {
3139
		$this->set_prop( 'remote_subscription_id', $value );
3140
    }
3141
3142
	/**
3143
	 * Set the invoice anonymize status.
3144
	 *
3145
	 * @since 2.8.22
3146
	 * @param  bool $is_anonymized is anonymized.
3147
	 */
3148
	public function set_is_anonymized( $is_anonymized ) {
3149
		$this->set_prop( 'is_anonymized', (bool) $is_anonymized );
3150
    }
3151
3152
    /*
3153
	|--------------------------------------------------------------------------
3154
	| Boolean methods
3155
	|--------------------------------------------------------------------------
3156
	|
3157
	| Return true or false.
3158
	|
3159
    */
3160
3161
    /**
3162
     * Checks if this is a parent invoice.
3163
     */
3164
    public function is_parent() {
3165
        $parent = $this->get_parent_id();
3166
        return apply_filters( 'wpinv_invoice_is_parent', empty( $parent ), $this );
3167
    }
3168
3169
    /**
3170
     * Checks if this is a renewal invoice.
3171
     */
3172
    public function is_renewal() {
3173
        return $this->is_recurring() && ! $this->is_parent();
3174
    }
3175
3176
    /**
3177
     * Checks if this is a recurring invoice.
3178
     */
3179
    public function is_recurring() {
3180
        return ! empty( $this->recurring_item );
3181
    }
3182
3183
    /**
3184
     * Checks if this is a taxable invoice.
3185
     */
3186
    public function is_taxable() {
3187
        return ! $this->get_disable_taxes();
3188
	}
3189
3190
	/**
3191
	 * @deprecated
3192
	 */
3193
	public function has_vat() {
3194
        return $this->is_taxable();
3195
	}
3196
3197
	/**
3198
	 * Checks to see if the invoice requires payment.
3199
	 */
3200
	public function is_free() {
3201
        $is_free = ( (float) wpinv_round_amount( $this->get_initial_total() ) == 0 );
3202
3203
		if ( $this->is_recurring() && $this->get_recurring_total() > 0 ) {
3204
			$is_free = false;
3205
		}
3206
3207
        return apply_filters( 'wpinv_invoice_is_free', $is_free, $this );
3208
    }
3209
3210
    /**
3211
     * Checks if the invoice is paid.
3212
     */
3213
    public function is_paid() {
3214
        $is_paid = $this->has_status( array( 'publish', 'wpi-processing', 'wpi-renewal' ) );
3215
        return apply_filters( 'wpinv_invoice_is_paid', $is_paid, $this );
3216
	}
3217
3218
	/**
3219
     * Checks if the invoice needs payment.
3220
     */
3221
	public function needs_payment() {
3222
		$needs_payment = ! $this->is_paid() && ! $this->is_refunded() && ! $this->is_free();
3223
        return apply_filters( 'wpinv_needs_payment', $needs_payment, $this );
3224
    }
3225
3226
	/**
3227
     * Checks if the invoice is refunded.
3228
     */
3229
	public function is_refunded() {
3230
        $is_refunded = $this->has_status( 'wpi-refunded' );
3231
        return apply_filters( 'wpinv_invoice_is_refunded', $is_refunded, $this );
3232
	}
3233
3234
	/**
3235
     * Checks if the invoice is held.
3236
     */
3237
	public function is_held() {
3238
        $is_held = $this->has_status( 'wpi-onhold' );
3239
        return apply_filters( 'wpinv_invoice_is_held', $is_held, $this );
3240
	}
3241
3242
	/**
3243
     * Checks if the invoice is due.
3244
     */
3245
	public function is_due() {
3246
		$due_date = $this->get_due_date();
3247
		return empty( $due_date ) ? false : current_time( 'timestamp' ) > strtotime( $due_date );
3248
	}
3249
3250
	/**
3251
     * Checks if the invoice is draft.
3252
     */
3253
	public function is_draft() {
3254
        return $this->has_status( 'draft, auto-draft' );
3255
	}
3256
3257
    /**
3258
     * Checks if the invoice has a given status.
3259
     */
3260
    public function has_status( $status ) {
3261
        $status = wpinv_parse_list( $status );
3262
        return apply_filters( 'wpinv_has_status', in_array( $this->get_status(), $status ), $status );
3263
	}
3264
3265
	/**
3266
     * Checks if the invoice is of a given type.
3267
     */
3268
    public function is_type( $type ) {
3269
        $type = wpinv_parse_list( $type );
3270
        return in_array( $this->get_type(), $type );
3271
    }
3272
3273
    /**
3274
     * Checks if this is a quote object.
3275
     *
3276
     * @since 1.0.15
3277
     */
3278
    public function is_quote() {
3279
        return 'wpi_quote' == $this->get_post_type();
3280
    }
3281
3282
    /**
3283
     * Check if the invoice (or it's parent has a free trial).
3284
     *
3285
     */
3286
    public function has_free_trial() {
3287
        return $this->is_recurring() && 0 == $this->get_initial_total();
3288
	}
3289
3290
	/**
3291
     * @deprecated
3292
     */
3293
    public function is_free_trial() {
3294
        return $this->has_free_trial();
3295
    }
3296
3297
	/**
3298
     * Check if the initial payment if 0.
3299
     *
3300
     */
3301
	public function is_initial_free() {
3302
        $is_initial_free = ! ( (float) wpinv_round_amount( $this->get_initial_total() ) > 0 );
3303
        return apply_filters( 'wpinv_invoice_is_initial_free', $is_initial_free, $this->get_cart_details(), $this );
3304
    }
3305
3306
	/**
3307
     * Check if the recurring item has a free trial.
3308
     *
3309
     */
3310
    public function item_has_free_trial() {
3311
3312
        // Ensure we have a recurring item.
3313
        if ( ! $this->is_recurring() ) {
3314
            return false;
3315
        }
3316
3317
        $item = $this->get_recurring( true );
3318
        return $item->has_free_trial();
3319
	}
3320
3321
	/**
3322
     * Check if the free trial is a result of a discount.
3323
     */
3324
    public function is_free_trial_from_discount() {
3325
		return $this->has_free_trial() && ! $this->item_has_free_trial();
3326
	}
3327
3328
	/**
3329
     * Checks if this is an anonymized invoice.
3330
     *
3331
     * @since 2.8.22
3332
     */
3333
    public function is_anonymized() {
3334
        return true === (bool) $this->get_is_anonymized();
3335
    }
3336
3337
	/**
3338
     * @deprecated
3339
     */
3340
    public function discount_first_payment_only() {
3341
3342
		$discount = wpinv_get_discount_obj( $this->get_discount_code() );
3343
        if ( ! $discount->exists() || ! $this->is_recurring() ) {
3344
            return true;
3345
        }
3346
3347
        return ! $discount->get_is_recurring();
3348
    }
3349
3350
    /*
3351
	|--------------------------------------------------------------------------
3352
	| Cart related methods
3353
	|--------------------------------------------------------------------------
3354
	|
3355
	| Do not forget to recalculate totals after calling the following methods.
3356
	|
3357
    */
3358
3359
    /**
3360
     * Adds an item to the invoice.
3361
     *
3362
     * @param GetPaid_Form_Item|array $item
3363
     * @return WP_Error|Bool
3364
     */
3365
    public function add_item( $item ) {
3366
3367
		if ( is_array( $item ) ) {
3368
			$item = $this->process_array_item( $item );
3369
		}
3370
3371
		if ( is_numeric( $item ) ) {
3372
			$item = new GetPaid_Form_Item( $item );
3373
		}
3374
3375
        // Make sure that it is available for purchase.
3376
		if ( $item->get_id() > 0 && ! $item->can_purchase() ) {
3377
			return new WP_Error( 'invalid_item', __( 'This item is not available for purchase', 'invoicing' ) );
3378
        }
3379
3380
        // Do we have a recurring item?
3381
		if ( $item->is_recurring() ) {
3382
			$this->recurring_item = $item->get_id();
3383
        }
3384
3385
        // Invoice id.
3386
        $item->invoice_id = (int) $this->get_id();
3387
3388
		// Remove duplicates.
3389
		$this->remove_item( $item->get_id() );
3390
3391
		if ( 0 == $item->get_quantity() ) {
3392
			return;
3393
		}
3394
3395
		// Retrieve all items.
3396
        $items   = $this->get_items();
3397
3398
		// Add new item.
3399
        $items[] = $item;
3400
3401
        $this->set_prop( 'items', $items );
3402
3403
		return true;
3404
	}
3405
3406
	/**
3407
	 * Converts an array to an item.
3408
	 *
3409
	 * @since 1.0.19
3410
	 * @return GetPaid_Form_Item
3411
	 */
3412
	protected function process_array_item( $array ) {
3413
3414
		$item_id = isset( $array['item_id'] ) ? $array['item_id'] : 0;
3415
		$item    = new GetPaid_Form_Item( $item_id );
3416
3417
		// Set item data.
3418
		foreach ( array( 'name', 'price', 'description' ) as $key ) {
3419
			if ( isset( $array[ "item_$key" ] ) ) {
3420
				$method = "set_$key";
3421
				$item->$method( $array[ "item_$key" ] );
3422
			}
3423
		}
3424
3425
		if ( isset( $array['quantity'] ) ) {
3426
			$item->set_quantity( $array['quantity'] );
3427
		}
3428
3429
		// Set item meta.
3430
		if ( isset( $array['meta'] ) && is_array( $array['meta'] ) ) {
3431
			$item->set_item_meta( $array['meta'] );
3432
		}
3433
3434
		return $item;
3435
3436
	}
3437
3438
    /**
3439
	 * Retrieves a specific item.
3440
	 *
3441
	 * @since 1.0.19
3442
	 * @return GetPaid_Form_Item|null
3443
	 */
3444
	public function get_item( $item_id ) {
3445
3446
		foreach ( $this->get_items() as $item ) {
3447
			if ( (int) $item_id == $item->get_id() ) {
3448
				return $item;
3449
			}
3450
		}
3451
3452
		return null;
3453
    }
3454
3455
    /**
3456
	 * Removes a specific item.
3457
	 *
3458
	 * @since 1.0.19
3459
	 */
3460
	public function remove_item( $item_id ) {
3461
		$items   = $this->get_items();
3462
		$item_id = (int) $item_id;
3463
3464
		foreach ( $items as $index => $item ) {
3465
			if ( (int) $item_id == $item->get_id() ) {
3466
				unset( $items[ $index ] );
3467
				$this->set_prop( 'items', $items );
3468
3469
				if ( $item_id == $this->recurring_item ) {
3470
					$this->recurring_item = null;
3471
				}
3472
}
3473
		}
3474
3475
    }
3476
3477
    /**
3478
	 * Adds a fee to the invoice.
3479
	 *
3480
	 * @param array $fee An array of fee details. name, initial_fee, and recurring_fee are required.
3481
	 * @since 1.0.19
3482
	 */
3483
    public function add_fee( $fee ) {
3484
3485
		$fees                 = $this->get_fees();
3486
		$fees[ $fee['name'] ] = $fee;
3487
		$this->set_prop( 'fees', $fees );
3488
3489
    }
3490
3491
    /**
3492
	 * Retrieves a specific fee.
3493
	 *
3494
	 * @since 1.0.19
3495
	 */
3496
	public function get_fee( $fee ) {
3497
        $fees = $this->get_fees();
3498
		return isset( $fees[ $fee ] ) ? $fees[ $fee ] : null;
3499
    }
3500
3501
    /**
3502
	 * Removes a specific fee.
3503
	 *
3504
	 * @since 1.0.19
3505
	 */
3506
	public function remove_fee( $fee ) {
3507
        $fees = $this->get_fees();
3508
        if ( isset( $fees[ $fee ] ) ) {
3509
            unset( $fees[ $fee ] );
3510
            $this->set_prop( 'fees', $fees );
3511
        }
3512
    }
3513
3514
	/**
3515
	 * Adds a discount to the invoice.
3516
	 *
3517
	 * @param array $discount An array of discount details. name, initial_discount, and recurring_discount are required. Include discount_code if the discount is from a discount code.
3518
	 * @since 1.0.19
3519
	 */
3520
	public function add_discount( $discount ) {
3521
3522
		$discounts = $this->get_discounts();
3523
		$discounts[ $discount['name'] ] = $discount;
3524
		$this->set_prop( 'discounts', $discounts );
3525
3526
	}
3527
3528
    /**
3529
	 * Retrieves a specific discount.
3530
	 *
3531
	 * @since 1.0.19
3532
	 * @return float
3533
	 */
3534
	public function get_discount( $discount = false ) {
3535
3536
		// Backwards compatibility.
3537
		if ( empty( $discount ) ) {
3538
			return $this->get_total_discount();
3539
		}
3540
3541
        $discounts = $this->get_discounts();
3542
		return isset( $discounts[ $discount ] ) ? $discounts[ $discount ] : null;
3543
    }
3544
3545
    /**
3546
	 * Removes a specific discount.
3547
	 *
3548
	 * @since 1.0.19
3549
	 */
3550
	public function remove_discount( $discount ) {
3551
        $discounts = $this->get_discounts();
3552
        if ( isset( $discounts[ $discount ] ) ) {
3553
            unset( $discounts[ $discount ] );
3554
            $this->set_prop( 'discounts', $discounts );
3555
        }
3556
3557
		if ( 'discount_code' == $discount ) {
3558
			foreach ( $this->get_items() as $item ) {
3559
				$item->item_discount           = 0;
3560
				$item->recurring_item_discount = 0;
3561
			}
3562
		}
3563
3564
    }
3565
3566
    /**
3567
     * Adds a tax to the invoice.
3568
     *
3569
     * @param array $tax An array of tax details. name, initial_tax, and recurring_tax are required.
3570
     */
3571
    public function add_tax( $tax ) {
3572
        if ( $this->is_taxable() ) {
3573
3574
            $taxes                 = $this->get_taxes();
3575
			$taxes[ $tax['name'] ] = $tax;
3576
			$this->set_prop( 'taxes', $tax );
3577
3578
        }
3579
    }
3580
3581
    /**
3582
	 * Retrieves a specific tax.
3583
	 *
3584
	 * @since 1.0.19
3585
	 */
3586
	public function get_tax( $tax = null ) {
3587
3588
		// Backwards compatibility.
3589
		if ( empty( $tax ) ) {
3590
			return $this->get_total_tax();
3591
		}
3592
3593
        $taxes = $this->get_taxes();
3594
		return isset( $taxes[ $tax ] ) ? $taxes[ $tax ] : null;
3595
    }
3596
3597
	public function get_tax_total_by_name( $name ) {
3598
		if ( $name && 0 === strpos( $name, 'tax__' ) ) {
3599
			$name = str_replace( 'tax__', '', $name );
3600
		}
3601
3602
		if ( empty( $name ) ) {
3603
			return 0;
3604
		}
3605
3606
		$tax = $this->get_tax( $name );
3607
3608
		if ( empty( $tax ) ) {
3609
			return 0;
3610
		}
3611
3612
        return $this->is_renewal() ? $tax['recurring_tax'] : $tax['initial_tax'];
3613
    }
3614
3615
	/**
3616
	 * Get tax item name.
3617
	 *
3618
	 * @since 2.8.8
3619
	 */
3620
	public function get_tax_item_name( $tax_key, $tax_item, $suffix = '' ) {
3621
		$tax_name = _x( 'Tax', 'Tax name', 'invoicing' );
3622
3623
		if ( ! empty( $tax_item ) && is_array( $tax_item ) && ! empty( $tax_item['name'] ) ) {
3624
			$tax_name = __( $tax_item['name'], 'invoicing' );
3625
		}
3626
3627
		if ( $suffix ) {
3628
			$tax_name .= $suffix;
3629
		}
3630
3631
		return apply_filters( 'wpinv_invoice_get_tax_name', $tax_name, $this, $tax_key, $tax_item, $suffix );
3632
	}
3633
3634
	/**
3635
	 * Get tax item amount.
3636
	 *
3637
	 * @since 2.8.8
3638
	 */
3639
	public function get_tax_item_amount( $tax_key, $tax_item, $with_currency = false ) {
3640
		$tax_amount = $this->get_tax_total_by_name( $tax_key );
3641
3642
		if ( $with_currency ) {
3643
			$tax_amount = wpinv_price( $tax_amount, $this->get_currency() );
3644
		}
3645
3646
		return apply_filters( 'wpinv_invoice_get_tax_amount', $tax_amount, $this, $tax_item, $with_currency );
3647
	}
3648
3649
	public function get_item_tax_name( $percentage = true, $sep = ' + ' ) {
3650
		$taxes = $this->get_taxes();
3651
3652
		if ( ! empty( $taxes ) && is_array( $taxes ) && count( $taxes ) == 1 && wpinv_display_individual_tax_rates() ) {
3653
			$names = array();
3654
3655
			foreach ( $taxes as $key => $tax ) {
3656
				if ( ! empty( $tax ) && ! empty( $tax['name'] ) ) {
3657
					$name = __( $tax['name'], 'invoicing' );
3658
3659
					$names[] = $name;
3660
				}
3661
			}
3662
3663
			if ( ! empty( $names ) ) {
3664
				$names = array_unique( $names );
3665
3666
				$tax_name = implode( $sep, $names );
3667
			}
3668
3669
			if ( $percentage ) {
3670
				$tax_name = wp_sprintf( _x( '%s (%%)', 'Tax name with %. Ex: Tax (%)', 'invoicing' ), $tax_name );
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tax_name does not seem to be defined for all execution paths leading up to this point.
Loading history...
3671
			}
3672
		} else {
3673
			$tax_name = $percentage ? __( 'Tax (%)', 'invoicing' ) : _x( 'Tax', 'Tax name', 'invoicing' );
3674
		}
3675
3676
		return apply_filters( 'wpinv_invoice_get_item_tax_name', $tax_name, $this, $percentage, $sep );
3677
	}
3678
3679
    /**
3680
	 * Removes a specific tax.
3681
	 *
3682
	 * @since 1.0.19
3683
	 */
3684
	public function remove_tax( $tax ) {
3685
        $taxes = $this->get_taxes();
3686
        if ( isset( $taxes[ $tax ] ) ) {
3687
            unset( $taxes[ $tax ] );
3688
            $this->set_prop( 'taxes', $taxes );
3689
        }
3690
    }
3691
3692
    /**
3693
	 * Recalculates the invoice subtotal.
3694
	 *
3695
	 * @since 1.0.19
3696
	 * @return float The recalculated subtotal
3697
	 */
3698
	public function recalculate_subtotal() {
3699
        $items     = $this->get_items();
3700
		$subtotal  = 0;
3701
		$recurring = 0;
3702
3703
        foreach ( $items as $item ) {
3704
			$subtotal  += $item->get_sub_total( 'edit' );
3705
			$recurring += $item->get_recurring_sub_total( 'edit' );
3706
        }
3707
3708
		if ( wpinv_prices_include_tax() ) {
3709
			$subtotal  = max( 0, $subtotal - $this->totals['tax']['initial'] );
3710
			$recurring = max( 0, $recurring - $this->totals['tax']['recurring'] );
3711
		}
3712
3713
		$current = $this->is_renewal() ? $recurring : $subtotal;
3714
		$this->set_subtotal( $current );
3715
3716
		$this->totals['subtotal'] = array(
3717
			'initial'   => $subtotal,
3718
			'recurring' => $recurring,
3719
		);
3720
3721
        return $current;
3722
    }
3723
3724
    /**
3725
	 * Recalculates the invoice discount total.
3726
	 *
3727
	 * @since 1.0.19
3728
	 * @return float The recalculated discount
3729
	 */
3730
	public function recalculate_total_discount() {
3731
		// Fix renewal invoice amount when tax + recurring discount applied.
3732
		if ( $this->is_renewal() && $this->get_discount_code() ) {
3733
			// Maybe recalculate discount (Pre-GetPaid Fix).
3734
			$discount = new WPInv_Discount( $this->get_discount_code() );
3735
3736
			if ( $discount->exists() && $discount->is_recurring() ) {
3737
				getpaid_calculate_invoice_discount( $this, $discount );
3738
			}
3739
		}
3740
3741
		$discounts = $this->get_discounts();
3742
		$discount  = 0;
3743
		$recurring = 0;
3744
3745
        foreach ( $discounts as $data ) {
3746
			$discount  += wpinv_sanitize_amount( $data['initial_discount'] );
3747
			$recurring += wpinv_sanitize_amount( $data['recurring_discount'] );
3748
		}
3749
3750
		$current = $this->is_renewal() ? $recurring : $discount;
3751
3752
		$this->set_total_discount( $current );
3753
3754
		$this->totals['discount'] = array(
3755
			'initial'   => $discount,
3756
			'recurring' => $recurring,
3757
		);
3758
3759
		return $current;
3760
3761
    }
3762
3763
    /**
3764
	 * Recalculates the invoice tax total.
3765
	 *
3766
	 * @since 1.0.19
3767
	 * @return float The recalculated tax
3768
	 */
3769
	public function recalculate_total_tax() {
3770
3771
		// Maybe disable taxes.
3772
		$vat_number = $this->get_vat_number();
3773
		$skip_tax   = GetPaid_Payment_Form_Submission_Taxes::is_eu_transaction( $this->get_country() ) && ! empty( $vat_number );
3774
3775
		if ( wpinv_is_base_country( $this->get_country() ) && 'vat_too' === wpinv_get_option( 'vat_same_country_rule', 'vat_too' ) ) {
3776
			$skip_tax = false;
3777
		}
3778
3779
		if ( ! wpinv_use_taxes() || $this->get_disable_taxes() || ! wpinv_is_country_taxable( $this->get_country() ) || $skip_tax ) {
3780
3781
			$this->totals['tax'] = array(
3782
				'initial'   => 0,
3783
				'recurring' => 0,
3784
			);
3785
3786
			$this->tax_rate = 0;
3787
3788
			$this->set_taxes( array() );
3789
			$current = 0;
3790
		} else {
3791
3792
			$item_taxes = array();
3793
3794
			foreach ( $this->get_items() as $item ) {
3795
				$rates    = getpaid_get_item_tax_rates( $item, $this->get_country(), $this->get_state() );
3796
				$rates    = getpaid_filter_item_tax_rates( $item, $rates );
3797
				$taxes    = getpaid_calculate_item_taxes( getpaid_get_taxable_amount( $item, false ), $rates );
3798
				$r_taxes  = getpaid_calculate_item_taxes( getpaid_get_taxable_amount( $item, true ), $rates );
3799
				foreach ( $taxes as $name => $amount ) {
3800
					$recurring = isset( $r_taxes[ $name ] ) ? $r_taxes[ $name ] : 0;
3801
					$tax       = getpaid_prepare_item_tax( $item, $name, $amount, $recurring );
3802
3803
					if ( ! isset( $item_taxes[ $name ] ) ) {
3804
						$item_taxes[ $name ] = $tax;
3805
						continue;
3806
					}
3807
3808
					$item_taxes[ $name ]['initial_tax']   += $tax['initial_tax'];
3809
					$item_taxes[ $name ]['recurring_tax'] += $tax['recurring_tax'];
3810
3811
				}
3812
			}
3813
3814
			$this->set_taxes( $item_taxes );
3815
3816
			$initial_tax   = array_sum( wp_list_pluck( $item_taxes, 'initial_tax' ) );
3817
			$recurring_tax = array_sum( wp_list_pluck( $item_taxes, 'recurring_tax' ) );
3818
3819
			$current = $this->is_renewal() ? $recurring_tax : $initial_tax;
3820
3821
			$this->totals['tax'] = array(
3822
				'initial'   => $initial_tax,
3823
				'recurring' => $recurring_tax,
3824
			);
3825
3826
		}
3827
3828
		$this->set_total_tax( $current );
3829
3830
		return $current;
3831
3832
    }
3833
3834
    /**
3835
	 * Recalculates the invoice fees total.
3836
	 *
3837
	 * @since 1.0.19
3838
	 * @return float The recalculated fee
3839
	 */
3840
	public function recalculate_total_fees() {
3841
		$fees      = $this->get_fees();
3842
		$fee       = 0;
3843
		$recurring = 0;
3844
3845
        foreach ( $fees as $data ) {
3846
			if( isset( $data['initial_fee'] ) ){
3847
				$fee += wpinv_sanitize_amount( $data['initial_fee'] );
3848
			}
3849
3850
			if( isset( $data['recurring_fee'] ) ){
3851
				$recurring += wpinv_sanitize_amount( $data['recurring_fee'] );
3852
			}
3853
		}
3854
3855
		$current = $this->is_renewal() ? $recurring : $fee;
3856
		$this->set_total_fees( $current );
3857
3858
		$this->totals['fee'] = array(
3859
			'initial'   => $fee,
3860
			'recurring' => $recurring,
3861
		);
3862
3863
        $this->set_total_fees( $fee );
3864
        return $current;
3865
    }
3866
3867
    /**
3868
	 * Recalculates the invoice total.
3869
	 *
3870
	 * @since 1.0.19
3871
     * @return float The invoice total
3872
	 */
3873
	public function recalculate_total() {
3874
        $this->recalculate_total_fees();
3875
        $this->recalculate_total_discount();
3876
		$this->recalculate_total_tax();
3877
		$this->recalculate_subtotal();
3878
		$this->set_total( $this->get_total_tax( 'edit' ) + $this->get_total_fees( 'edit' ) + $this->get_subtotal( 'edit' ) - $this->get_total_discount( 'edit' ) );
3879
		return $this->get_total();
3880
	}
3881
3882
	/**
3883
	 * @deprecated
3884
	 */
3885
    public function recalculate_totals() {
3886
        $this->recalculate_total();
3887
        $this->save( true );
3888
        return $this;
3889
    }
3890
3891
    /**
3892
     * Convert this to an array.
3893
     */
3894
    public function array_convert() {
3895
        return $this->get_data();
3896
    }
3897
3898
	/**
3899
     * Adds a system note to an invoice.
3900
     *
3901
     * @param string $note The note being added.
3902
	 * @return int|false The new note's ID on success, false on failure.
3903
     *
3904
     */
3905
    public function add_system_note( $note ) {
3906
		return $this->add_note( $note, false, false, true );
3907
	}
3908
3909
    /**
3910
     * Adds a note to an invoice.
3911
     *
3912
     * @param string $note The note being added.
3913
	 * @return int|false The new note's ID on success, false on failure.
3914
     *
3915
     */
3916
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3917
3918
        // Bail if no note specified or this invoice is not yet saved.
3919
        if ( ! $note || $this->get_id() == 0 || ( ! is_user_logged_in() && ! $system ) ) {
3920
            return false;
3921
        }
3922
3923
		$author       = 'System';
3924
		$author_email = '[email protected]';
3925
3926
		// If this is an admin comment or it has been added by the user.
3927
		if ( is_user_logged_in() && ( ! $system || $added_by_user ) ) {
3928
			$user         = get_user_by( 'id', get_current_user_id() );
3929
            $author       = $user->display_name;
3930
            $author_email = $user->user_email;
3931
		}
3932
3933
		return getpaid_notes()->add_invoice_note( $this, $note, $author, $author_email, $customer_type );
3934
3935
	}
3936
3937
	/**
3938
     * Generates a unique key for the invoice.
3939
     */
3940
    public function generate_key( $string = '' ) {
3941
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3942
        return strtolower(
3943
            $string . md5( $this->get_id() . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3944
        );
3945
    }
3946
3947
    /**
3948
     * Generates a new number for the invoice.
3949
     */
3950
    public function generate_number() {
3951
        $number = $this->get_id();
3952
3953
        if ( wpinv_sequential_number_active( $this->get_post_type() ) ) {
3954
            $number = wpinv_get_next_invoice_number( $this->get_post_type() );
3955
        }
3956
3957
		return wpinv_format_invoice_number( $number, $this->get_post_type() );
3958
3959
	}
3960
3961
	/**
3962
	 * Handle the status transition.
3963
	 */
3964
	protected function status_transition() {
3965
		$status_transition = $this->status_transition;
3966
3967
		// Reset status transition variable.
3968
		$this->status_transition = false;
3969
3970
		if ( $status_transition ) {
3971
			try {
3972
3973
				// Fire a hook for the status change.
3974
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this, $status_transition );
3975
3976
				// @deprecated this is deprecated and will be removed in the future.
3977
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3978
3979
				if ( ! empty( $status_transition['from'] ) ) {
3980
3981
					/* translators: 1: old invoice status 2: new invoice status */
3982
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'], $this ), wpinv_status_nicename( $status_transition['to'], $this ) );
3983
3984
					// Fire another hook.
3985
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this );
3986
					do_action( 'getpaid_invoice_status_changed', $this, $status_transition['from'], $status_transition['to'] );
3987
3988
					// @deprecated this is deprecated and will be removed in the future.
3989
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3990
3991
					// Note the transition occurred.
3992
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), false, $status_transition['manual'] );
3993
3994
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3995
					if (
3996
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'pending', 'wpi-pending', 'wpi-failed', 'wpi-refunded', 'wpi-onhold' ), true )
3997
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3998
					) {
3999
						do_action( 'getpaid_invoice_payment_status_changed', $this, $status_transition );
4000
					}
4001
4002
					// Work out if this was for a payment reversal, and trigger a payment_status_reversed hook instead.
4003
					if (
4004
						in_array( $status_transition['from'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
4005
						&& in_array( $status_transition['to'], array( 'wpi-cancelled', 'pending', 'wpi-pending', 'wpi-failed', 'wpi-refunded', 'wpi-onhold' ), true )
4006
					) {
4007
						do_action( 'getpaid_invoice_payment_status_reversed', $this, $status_transition );
4008
					}
4009
				} else {
4010
					/* translators: %s: new invoice status */
4011
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'], $this ) );
4012
4013
					// Note the transition occurred.
4014
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
4015
4016
				}
4017
			} catch ( Exception $e ) {
4018
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
4019
			}
4020
		}
4021
	}
4022
4023
	/**
4024
	 * Updates an invoice status.
4025
	 */
4026
	public function update_status( $new_status = false, $note = '', $manual = false ) {
4027
4028
		// Fires before updating a status.
4029
		do_action( 'wpinv_before_invoice_status_change', $this->get_id(), $new_status, $this->get_status( 'edit' ) );
4030
4031
		// Update the status.
4032
		$this->set_status( $new_status, $note, $manual );
4033
4034
		// Save the order.
4035
		return $this->save();
4036
4037
	}
4038
4039
	/**
4040
	 * @deprecated
4041
	 */
4042
	public function refresh_item_ids() {
4043
        $item_ids = implode( ',', array_unique( wp_list_pluck( $this->get_cart_details(), 'item_id' ) ) );
4044
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
4045
	}
4046
4047
	/**
4048
	 * @deprecated
4049
	 */
4050
	public function update_items( $temp = false ) {
4051
4052
		$this->set_items( $this->get_items() );
4053
4054
		if ( ! $temp ) {
4055
			$this->save();
4056
		}
4057
4058
        return $this;
4059
	}
4060
4061
	/**
4062
	 * @deprecated
4063
	 */
4064
    public function validate_discount() {
4065
4066
        $discount_code = $this->get_discount_code();
4067
4068
        if ( empty( $discount_code ) ) {
4069
            return false;
4070
        }
4071
4072
        $discount = wpinv_get_discount_obj( $discount_code );
4073
4074
        // Ensure it is active.
4075
        return $discount->exists();
4076
4077
    }
4078
4079
	/**
4080
	 * Refunds an invoice.
4081
	 */
4082
    public function refund() {
4083
		$this->set_status( 'wpi-refunded' );
4084
        $this->save();
4085
	}
4086
4087
	/**
4088
	 * Marks an invoice as paid.
4089
	 *
4090
	 * @param string $transaction_id
4091
	 */
4092
    public function mark_paid( $transaction_id = null, $note = '' ) {
4093
4094
		// Set the transaction id.
4095
		if ( empty( $transaction_id ) ) {
4096
			$transaction_id = $this->generate_key( 'trans_' );
4097
		}
4098
4099
		if ( ! $this->get_transaction_id() ) {
4100
			$this->set_transaction_id( $transaction_id );
4101
		}
4102
4103
		if ( $this->is_paid() && 'wpi-processing' !== $this->get_status() ) {
4104
			return $this->save();
4105
		}
4106
4107
		// Set the completed date.
4108
		$this->set_date_completed( current_time( 'mysql' ) );
4109
4110
		// Set the new status.
4111
		$gateway = sanitize_text_field( $this->get_gateway_title() );
4112
		if ( $this->is_renewal() || ! $this->is_parent() ) {
4113
4114
			$_note = wp_sprintf( __( 'Renewed via %s', 'invoicing' ), $gateway );
4115
			$_note = $_note . empty( $note ) ? '' : " ($note)";
4116
4117
			if ( 'none' == $this->get_gateway() ) {
4118
				$_note = $note;
4119
			}
4120
4121
			$this->set_status( 'wpi-renewal', $_note );
4122
4123
		} else {
4124
4125
			$_note = wp_sprintf( __( 'Paid via %s', 'invoicing' ), $gateway );
4126
			$_note = $_note . empty( $note ) ? '' : " ($note)";
4127
4128
			if ( 'none' == $this->get_gateway() ) {
4129
				$_note = $note;
4130
			}
4131
4132
			$this->set_status( 'publish', $_note );
4133
4134
		}
4135
4136
		// Set checkout mode.
4137
		$mode = wpinv_is_test_mode( $this->get_gateway() ) ? 'test' : 'live';
4138
		$this->set_mode( $mode );
4139
4140
		// Save the invoice.
4141
        $this->save();
4142
	}
4143
4144
	/**
4145
	 * Save data to the database.
4146
	 *
4147
	 * @since 1.0.19
4148
	 * @return int invoice ID
4149
	 */
4150
	public function save() {
4151
		$this->maybe_set_date_paid();
4152
		$this->maybe_set_key();
4153
		parent::save();
4154
		$this->clear_cache();
4155
		$this->status_transition();
4156
		return $this->get_id();
4157
	}
4158
4159
	/**
4160
     * Clears the subscription's cache.
4161
     */
4162
    public function clear_cache() {
4163
		if ( $this->get_key() ) {
4164
			wp_cache_delete( $this->get_key(), 'getpaid_invoice_keys_to_invoice_ids' );
4165
		}
4166
4167
		if ( $this->get_number() ) {
4168
			wp_cache_delete( $this->get_number(), 'getpaid_invoice_numbers_to_invoice_ids' );
4169
		}
4170
4171
		if ( $this->get_transaction_id() ) {
4172
			wp_cache_delete( $this->get_transaction_id(), 'getpaid_invoice_transaction_ids_to_invoice_ids' );
4173
		}
4174
	}
4175
4176
}
4177