Passed
Push — master ( cb75a2...6929e7 )
by Brian
05:54 queued 11s
created

WPInv_Invoice::get_all_statuses()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

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

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

153
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( /** @scrutinizer ignore-type */ $invoice, 'key' ) ) {
Loading history...
154
			$this->set_id( $invoice_id );
155
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'number' ) ) {
156
			$this->set_id( $invoice_id );
157
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'transaction_id' ) ) {
158
			$this->set_id( $invoice_id );
159
		}else {
160
			$this->set_object_read( true );
161
		}
162
163
        // Load the datastore.
164
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
165
166
		if ( $this->get_id() > 0 ) {
167
            $this->post = get_post( $this->get_id() );
168
            $this->ID   = $this->get_id();
0 ignored issues
show
Bug Best Practice introduced by
The property ID does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
169
			$this->data_store->read( $this );
170
        }
171
172
    }
173
174
    /**
175
	 * Given an invoice key/number, it returns its id.
176
	 *
177
	 *
178
	 * @static
179
	 * @param string $value The invoice key or number
180
	 * @param string $field Either key, transaction_id or number.
181
	 * @since 1.0.15
182
	 * @return int
183
	 */
184
	public static function get_invoice_id_by_field( $value, $field = 'key' ) {
185
        global $wpdb;
186
187
		// Trim the value.
188
		$value = trim( $value );
189
190
		if ( empty( $value ) ) {
191
			return 0;
192
		}
193
194
        // Valid fields.
195
        $fields = array( 'key', 'number', 'transaction_id' );
196
197
		// Ensure a field has been passed.
198
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
199
			return 0;
200
		}
201
202
		// Maybe retrieve from the cache.
203
		$invoice_id   = wp_cache_get( $value, "getpaid_invoice_{$field}s_to_invoice_ids" );
204
		if ( ! empty( $invoice_id ) ) {
205
			return $invoice_id;
206
		}
207
208
        // Fetch from the db.
209
        $table       = $wpdb->prefix . 'getpaid_invoices';
210
        $invoice_id  = $wpdb->get_var(
211
            $wpdb->prepare( "SELECT `post_id` FROM $table WHERE `$field`=%s LIMIT 1", $value )
212
        );
213
214
		if ( empty( $invoice_id ) ) {
215
			return 0;
216
		}
217
218
		// Update the cache with our data
219
		wp_cache_set( $value, $invoice_id, "getpaid_invoice_{$field}s_to_invoice_ids" );
220
221
		return $invoice_id;
222
    }
223
224
    /**
225
     * Checks if an invoice key is set.
226
     */
227
    public function _isset( $key ) {
228
        return isset( $this->data[$key] ) || method_exists( $this, "get_$key" );
229
    }
230
231
    /*
232
	|--------------------------------------------------------------------------
233
	| CRUD methods
234
	|--------------------------------------------------------------------------
235
	|
236
	| Methods which create, read, update and delete items from the database.
237
	|
238
    */
239
240
    /*
241
	|--------------------------------------------------------------------------
242
	| Getters
243
	|--------------------------------------------------------------------------
244
    */
245
246
    /**
247
	 * Get parent invoice ID.
248
	 *
249
	 * @since 1.0.19
250
	 * @param  string $context View or edit context.
251
	 * @return int
252
	 */
253
	public function get_parent_id( $context = 'view' ) {
254
		return (int) $this->get_prop( 'parent_id', $context );
255
    }
256
257
    /**
258
	 * Get parent invoice.
259
	 *
260
	 * @since 1.0.19
261
	 * @return WPInv_Invoice
262
	 */
263
    public function get_parent_payment() {
264
        return new WPInv_Invoice( $this->get_parent_id() );
265
    }
266
267
    /**
268
	 * Alias for self::get_parent_payment().
269
	 *
270
	 * @since 1.0.19
271
	 * @return WPInv_Invoice
272
	 */
273
    public function get_parent() {
274
        return $this->get_parent_payment();
275
    }
276
277
    /**
278
	 * Get invoice status.
279
	 *
280
	 * @since 1.0.19
281
	 * @param  string $context View or edit context.
282
	 * @return string
283
	 */
284
	public function get_status( $context = 'view' ) {
285
		return $this->get_prop( 'status', $context );
286
	}
287
	
288
	/**
289
	 * Retrieves an array of possible invoice statuses.
290
	 *
291
	 * @since 1.0.19
292
	 * @return array
293
	 */
294
	public function get_all_statuses() {
295
		
296
		$statuses = wpinv_get_invoice_statuses( true, true, $this );
297
298
		// For backwards compatibility.
299
		if ( $this->is_quote() && class_exists( 'Wpinv_Quotes_Shared' ) ) {
300
            $statuses = Wpinv_Quotes_Shared::wpinv_get_quote_statuses();
0 ignored issues
show
Bug introduced by
The type Wpinv_Quotes_Shared was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
301
		}
302
303
		return $statuses;
304
    }
305
306
    /**
307
	 * Get invoice status nice name.
308
	 *
309
	 * @since 1.0.19
310
	 * @return string
311
	 */
312
    public function get_status_nicename() {
313
		$statuses = $this->get_all_statuses();
314
315
        $status = isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : $this->get_status();
316
317
        return apply_filters( 'wpinv_get_invoice_status_nicename', $status, $this );
318
    }
319
320
    /**
321
	 * Get plugin version when the invoice was created.
322
	 *
323
	 * @since 1.0.19
324
	 * @param  string $context View or edit context.
325
	 * @return string
326
	 */
327
	public function get_version( $context = 'view' ) {
328
		return $this->get_prop( 'version', $context );
329
	}
330
331
	/**
332
	 * @deprecated
333
	 */
334
	public function get_invoice_date( $formatted = true ) {
335
        $date_completed = $this->get_date_completed();
336
        $invoice_date   = $date_completed != '0000-00-00 00:00:00' ? $date_completed : '';
337
338
        if ( $invoice_date == '' ) {
339
            $date_created   = $this->get_date_created();
340
            $invoice_date   = $date_created != '0000-00-00 00:00:00' ? $date_created : '';
341
        }
342
343
        if ( $formatted && $invoice_date ) {
344
            $invoice_date   = date_i18n( get_option( 'date_format' ), strtotime( $invoice_date ) );
0 ignored issues
show
Bug introduced by
It seems like get_option('date_format') can also be of type false; however, parameter $format of date_i18n() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

344
            $invoice_date   = date_i18n( /** @scrutinizer ignore-type */ get_option( 'date_format' ), strtotime( $invoice_date ) );
Loading history...
345
        }
346
347
        return apply_filters( 'wpinv_get_invoice_date', $invoice_date, $formatted, $this->get_id(), $this );
348
    }
349
350
    /**
351
	 * Get date when the invoice was created.
352
	 *
353
	 * @since 1.0.19
354
	 * @param  string $context View or edit context.
355
	 * @return string
356
	 */
357
	public function get_date_created( $context = 'view' ) {
358
		return $this->get_prop( 'date_created', $context );
359
	}
360
	
361
	/**
362
	 * Alias for self::get_date_created().
363
	 *
364
	 * @since 1.0.19
365
	 * @param  string $context View or edit context.
366
	 * @return string
367
	 */
368
	public function get_created_date( $context = 'view' ) {
369
		return $this->get_date_created( $context );
370
    }
371
372
    /**
373
	 * Get GMT date when the invoice was created.
374
	 *
375
	 * @since 1.0.19
376
	 * @param  string $context View or edit context.
377
	 * @return string
378
	 */
379
	public function get_date_created_gmt( $context = 'view' ) {
380
        $date = $this->get_date_created( $context );
381
382
        if ( $date ) {
383
            $date = get_gmt_from_date( $date );
384
        }
385
		return $date;
386
    }
387
388
    /**
389
	 * Get date when the invoice was last modified.
390
	 *
391
	 * @since 1.0.19
392
	 * @param  string $context View or edit context.
393
	 * @return string
394
	 */
395
	public function get_date_modified( $context = 'view' ) {
396
		return $this->get_prop( 'date_modified', $context );
397
	}
398
399
	/**
400
	 * Alias for self::get_date_modified().
401
	 *
402
	 * @since 1.0.19
403
	 * @param  string $context View or edit context.
404
	 * @return string
405
	 */
406
	public function get_modified_date( $context = 'view' ) {
407
		return $this->get_date_modified( $context );
408
    }
409
410
    /**
411
	 * Get GMT date when the invoice was last modified.
412
	 *
413
	 * @since 1.0.19
414
	 * @param  string $context View or edit context.
415
	 * @return string
416
	 */
417
	public function get_date_modified_gmt( $context = 'view' ) {
418
        $date = $this->get_date_modified( $context );
419
420
        if ( $date ) {
421
            $date = get_gmt_from_date( $date );
422
        }
423
		return $date;
424
    }
425
426
    /**
427
	 * Get the invoice due date.
428
	 *
429
	 * @since 1.0.19
430
	 * @param  string $context View or edit context.
431
	 * @return string
432
	 */
433
	public function get_due_date( $context = 'view' ) {
434
		return $this->get_prop( 'due_date', $context );
435
    }
436
437
    /**
438
	 * Alias for self::get_due_date().
439
	 *
440
	 * @since 1.0.19
441
	 * @param  string $context View or edit context.
442
	 * @return string
443
	 */
444
	public function get_date_due( $context = 'view' ) {
445
		return $this->get_due_date( $context );
446
    }
447
448
    /**
449
	 * Get the invoice GMT due date.
450
	 *
451
	 * @since 1.0.19
452
	 * @param  string $context View or edit context.
453
	 * @return string
454
	 */
455
	public function get_due_date_gmt( $context = 'view' ) {
456
        $date = $this->get_due_date( $context );
457
458
        if ( $date ) {
459
            $date = get_gmt_from_date( $date );
460
        }
461
		return $date;
462
    }
463
464
    /**
465
	 * Alias for self::get_due_date_gmt().
466
	 *
467
	 * @since 1.0.19
468
	 * @param  string $context View or edit context.
469
	 * @return string
470
	 */
471
	public function get_gmt_date_due( $context = 'view' ) {
472
		return $this->get_due_date_gmt( $context );
473
    }
474
475
    /**
476
	 * Get date when the invoice was completed.
477
	 *
478
	 * @since 1.0.19
479
	 * @param  string $context View or edit context.
480
	 * @return string
481
	 */
482
	public function get_completed_date( $context = 'view' ) {
483
		return $this->get_prop( 'completed_date', $context );
484
    }
485
486
    /**
487
	 * Alias for self::get_completed_date().
488
	 *
489
	 * @since 1.0.19
490
	 * @param  string $context View or edit context.
491
	 * @return string
492
	 */
493
	public function get_date_completed( $context = 'view' ) {
494
		return $this->get_completed_date( $context );
495
    }
496
497
    /**
498
	 * Get GMT date when the invoice was was completed.
499
	 *
500
	 * @since 1.0.19
501
	 * @param  string $context View or edit context.
502
	 * @return string
503
	 */
504
	public function get_completed_date_gmt( $context = 'view' ) {
505
        $date = $this->get_completed_date( $context );
506
507
        if ( $date ) {
508
            $date = get_gmt_from_date( $date );
509
        }
510
		return $date;
511
    }
512
513
    /**
514
	 * Alias for self::get_completed_date_gmt().
515
	 *
516
	 * @since 1.0.19
517
	 * @param  string $context View or edit context.
518
	 * @return string
519
	 */
520
	public function get_gmt_completed_date( $context = 'view' ) {
521
		return $this->get_completed_date_gmt( $context );
522
    }
523
524
    /**
525
	 * Get the invoice number.
526
	 *
527
	 * @since 1.0.19
528
	 * @param  string $context View or edit context.
529
	 * @return string
530
	 */
531
	public function get_number( $context = 'view' ) {
532
        $number = $this->get_prop( 'number', $context );
533
534
        if ( empty( $number ) ) {
535
            $number = $this->generate_number();
536
            $this->set_number( $number );
537
        }
538
539
		return $number;
540
    }
541
542
    /**
543
	 * Get the invoice key.
544
	 *
545
	 * @since 1.0.19
546
	 * @param  string $context View or edit context.
547
	 * @return string
548
	 */
549
	public function get_key( $context = 'view' ) {
550
        $key = $this->get_prop( 'key', $context );
551
552
        if ( empty( $key ) ) {
553
            $key = $this->generate_key( $this->post_type );
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
554
            $this->set_key( $key );
555
        }
556
557
		return $key;
558
    }
559
560
    /**
561
	 * Get the invoice type.
562
	 *
563
	 * @since 1.0.19
564
	 * @param  string $context View or edit context.
565
	 * @return string
566
	 */
567
	public function get_type( $context = 'view' ) {
568
        return $this->get_prop( 'type', $context );
569
	}
570
571
	/**
572
	 * @deprecated
573
	 */
574
	public function get_invoice_quote_type( $post_id ) {
575
        if ( empty( $post_id ) ) {
576
            return '';
577
        }
578
579
        $type = get_post_type( $post_id );
580
581
        if ( 'wpi_invoice' === $type ) {
582
            $post_type = __('Invoice', 'invoicing');
583
        } else{
584
            $post_type = __('Quote', 'invoicing');
585
        }
586
587
        return apply_filters('get_invoice_type_label', $post_type, $post_id);
588
    }
589
590
    /**
591
	 * Get the invoice post type.
592
	 *
593
	 * @since 1.0.19
594
	 * @param  string $context View or edit context.
595
	 * @return string
596
	 */
597
	public function get_post_type( $context = 'view' ) {
598
        return $this->get_prop( 'post_type', $context );
599
    }
600
601
    /**
602
	 * Get the invoice mode.
603
	 *
604
	 * @since 1.0.19
605
	 * @param  string $context View or edit context.
606
	 * @return string
607
	 */
608
	public function get_mode( $context = 'view' ) {
609
        return $this->get_prop( 'mode', $context );
610
    }
611
612
    /**
613
	 * Get the invoice path.
614
	 *
615
	 * @since 1.0.19
616
	 * @param  string $context View or edit context.
617
	 * @return string
618
	 */
619
	public function get_path( $context = 'view' ) {
620
        $path = $this->get_prop( 'path', $context );
621
622
        if ( empty( $path ) ) {
623
            $prefix = apply_filters( 'wpinv_post_name_prefix', 'inv-', $this->post_type );
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
624
            $path   = sanitize_title( $prefix . $this->get_id() );
625
        }
626
627
		return $path;
628
    }
629
630
    /**
631
	 * Get the invoice name/title.
632
	 *
633
	 * @since 1.0.19
634
	 * @param  string $context View or edit context.
635
	 * @return string
636
	 */
637
	public function get_name( $context = 'view' ) {
638
        $name = $this->get_prop( 'title', $context );
639
640
		return empty( $name ) ? $this->get_number( $context ) : $name;
641
    }
642
643
    /**
644
	 * Alias of self::get_name().
645
	 *
646
	 * @since 1.0.19
647
	 * @param  string $context View or edit context.
648
	 * @return string
649
	 */
650
	public function get_title( $context = 'view' ) {
651
		return $this->get_name( $context );
652
    }
653
654
    /**
655
	 * Get the invoice description.
656
	 *
657
	 * @since 1.0.19
658
	 * @param  string $context View or edit context.
659
	 * @return string
660
	 */
661
	public function get_description( $context = 'view' ) {
662
		return $this->get_prop( 'description', $context );
663
    }
664
665
    /**
666
	 * Alias of self::get_description().
667
	 *
668
	 * @since 1.0.19
669
	 * @param  string $context View or edit context.
670
	 * @return string
671
	 */
672
	public function get_excerpt( $context = 'view' ) {
673
		return $this->get_description( $context );
674
    }
675
676
    /**
677
	 * Alias of self::get_description().
678
	 *
679
	 * @since 1.0.19
680
	 * @param  string $context View or edit context.
681
	 * @return string
682
	 */
683
	public function get_summary( $context = 'view' ) {
684
		return $this->get_description( $context );
685
    }
686
687
    /**
688
	 * Returns the user info.
689
	 *
690
	 * @since 1.0.19
691
     * @param  string $context View or edit context.
692
	 * @return array
693
	 */
694
    public function get_user_info( $context = 'view' ) {
695
696
        $user_info = array(
697
            'user_id'    => $this->get_user_id( $context ),
698
            'email'      => $this->get_email( $context ),
699
            'first_name' => $this->get_first_name( $context ),
700
            'last_name'  => $this->get_last_name( $context ),
701
            'address'    => $this->get_address( $context ),
702
            'phone'      => $this->get_phone( $context ),
703
            'city'       => $this->get_city( $context ),
704
            'country'    => $this->get_country( $context ),
705
            'state'      => $this->get_state( $context ),
706
            'zip'        => $this->get_zip( $context ),
707
            'company'    => $this->get_company( $context ),
708
            'vat_number' => $this->get_vat_number( $context ),
709
            'discount'   => $this->get_discount_code( $context ),
710
		);
711
712
		return apply_filters( 'wpinv_user_info', $user_info, $this->get_id(), $this );
713
714
    }
715
716
    /**
717
	 * Get the customer id.
718
	 *
719
	 * @since 1.0.19
720
	 * @param  string $context View or edit context.
721
	 * @return int
722
	 */
723
	public function get_author( $context = 'view' ) {
724
		return (int) $this->get_prop( 'author', $context );
725
    }
726
727
    /**
728
	 * Alias of self::get_author().
729
	 *
730
	 * @since 1.0.19
731
	 * @param  string $context View or edit context.
732
	 * @return int
733
	 */
734
	public function get_user_id( $context = 'view' ) {
735
		return $this->get_author( $context );
736
    }
737
738
     /**
739
	 * Alias of self::get_author().
740
	 *
741
	 * @since 1.0.19
742
	 * @param  string $context View or edit context.
743
	 * @return int
744
	 */
745
	public function get_customer_id( $context = 'view' ) {
746
		return $this->get_author( $context );
747
    }
748
749
    /**
750
	 * Get the customer's ip.
751
	 *
752
	 * @since 1.0.19
753
	 * @param  string $context View or edit context.
754
	 * @return string
755
	 */
756
	public function get_ip( $context = 'view' ) {
757
		return $this->get_prop( 'user_ip', $context );
758
    }
759
760
    /**
761
	 * Alias of self::get_ip().
762
	 *
763
	 * @since 1.0.19
764
	 * @param  string $context View or edit context.
765
	 * @return string
766
	 */
767
	public function get_user_ip( $context = 'view' ) {
768
		return $this->get_ip( $context );
769
    }
770
771
     /**
772
	 * Alias of self::get_ip().
773
	 *
774
	 * @since 1.0.19
775
	 * @param  string $context View or edit context.
776
	 * @return string
777
	 */
778
	public function get_customer_ip( $context = 'view' ) {
779
		return $this->get_ip( $context );
780
    }
781
782
    /**
783
	 * Get the customer's first name.
784
	 *
785
	 * @since 1.0.19
786
	 * @param  string $context View or edit context.
787
	 * @return string
788
	 */
789
	public function get_first_name( $context = 'view' ) {
790
		return $this->get_prop( 'first_name', $context );
791
    }
792
793
    /**
794
	 * Alias of self::get_first_name().
795
	 *
796
	 * @since 1.0.19
797
	 * @param  string $context View or edit context.
798
	 * @return int
799
	 */
800
	public function get_user_first_name( $context = 'view' ) {
801
		return $this->get_first_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_first_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
802
    }
803
804
     /**
805
	 * Alias of self::get_first_name().
806
	 *
807
	 * @since 1.0.19
808
	 * @param  string $context View or edit context.
809
	 * @return int
810
	 */
811
	public function get_customer_first_name( $context = 'view' ) {
812
		return $this->get_first_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_first_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
813
    }
814
815
    /**
816
	 * Get the customer's last name.
817
	 *
818
	 * @since 1.0.19
819
	 * @param  string $context View or edit context.
820
	 * @return string
821
	 */
822
	public function get_last_name( $context = 'view' ) {
823
		return $this->get_prop( 'last_name', $context );
824
    }
825
826
    /**
827
	 * Alias of self::get_last_name().
828
	 *
829
	 * @since 1.0.19
830
	 * @param  string $context View or edit context.
831
	 * @return int
832
	 */
833
	public function get_user_last_name( $context = 'view' ) {
834
		return $this->get_last_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_last_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
835
    }
836
837
    /**
838
	 * Alias of self::get_last_name().
839
	 *
840
	 * @since 1.0.19
841
	 * @param  string $context View or edit context.
842
	 * @return int
843
	 */
844
	public function get_customer_last_name( $context = 'view' ) {
845
		return $this->get_last_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_last_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
846
    }
847
848
    /**
849
	 * Get the customer's full name.
850
	 *
851
	 * @since 1.0.19
852
	 * @param  string $context View or edit context.
853
	 * @return string
854
	 */
855
	public function get_full_name( $context = 'view' ) {
856
		return trim( $this->get_first_name( $context ) . ' ' . $this->get_last_name( $context ) );
857
    }
858
859
    /**
860
	 * Alias of self::get_full_name().
861
	 *
862
	 * @since 1.0.19
863
	 * @param  string $context View or edit context.
864
	 * @return int
865
	 */
866
	public function get_user_full_name( $context = 'view' ) {
867
		return $this->get_full_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_full_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
868
    }
869
870
    /**
871
	 * Alias of self::get_full_name().
872
	 *
873
	 * @since 1.0.19
874
	 * @param  string $context View or edit context.
875
	 * @return int
876
	 */
877
	public function get_customer_full_name( $context = 'view' ) {
878
		return $this->get_full_name( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_full_name($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
879
    }
880
881
    /**
882
	 * Get the customer's phone number.
883
	 *
884
	 * @since 1.0.19
885
	 * @param  string $context View or edit context.
886
	 * @return string
887
	 */
888
	public function get_phone( $context = 'view' ) {
889
		return $this->get_prop( 'phone', $context );
890
    }
891
892
    /**
893
	 * Alias of self::get_phone().
894
	 *
895
	 * @since 1.0.19
896
	 * @param  string $context View or edit context.
897
	 * @return int
898
	 */
899
	public function get_phone_number( $context = 'view' ) {
900
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
901
    }
902
903
    /**
904
	 * Alias of self::get_phone().
905
	 *
906
	 * @since 1.0.19
907
	 * @param  string $context View or edit context.
908
	 * @return int
909
	 */
910
	public function get_user_phone( $context = 'view' ) {
911
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
912
    }
913
914
    /**
915
	 * Alias of self::get_phone().
916
	 *
917
	 * @since 1.0.19
918
	 * @param  string $context View or edit context.
919
	 * @return int
920
	 */
921
	public function get_customer_phone( $context = 'view' ) {
922
		return $this->get_phone( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_phone($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
923
    }
924
925
    /**
926
	 * Get the customer's email address.
927
	 *
928
	 * @since 1.0.19
929
	 * @param  string $context View or edit context.
930
	 * @return string
931
	 */
932
	public function get_email( $context = 'view' ) {
933
		return $this->get_prop( 'email', $context );
934
    }
935
936
    /**
937
	 * Alias of self::get_email().
938
	 *
939
	 * @since 1.0.19
940
	 * @param  string $context View or edit context.
941
	 * @return string
942
	 */
943
	public function get_email_address( $context = 'view' ) {
944
		return $this->get_email( $context );
945
    }
946
947
    /**
948
	 * Alias of self::get_email().
949
	 *
950
	 * @since 1.0.19
951
	 * @param  string $context View or edit context.
952
	 * @return int
953
	 */
954
	public function get_user_email( $context = 'view' ) {
955
		return $this->get_email( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_email($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
956
    }
957
958
    /**
959
	 * Alias of self::get_email().
960
	 *
961
	 * @since 1.0.19
962
	 * @param  string $context View or edit context.
963
	 * @return int
964
	 */
965
	public function get_customer_email( $context = 'view' ) {
966
		return $this->get_email( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_email($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
967
    }
968
969
    /**
970
	 * Get the customer's country.
971
	 *
972
	 * @since 1.0.19
973
	 * @param  string $context View or edit context.
974
	 * @return string
975
	 */
976
	public function get_country( $context = 'view' ) {
977
		$country = $this->get_prop( 'country', $context );
978
		return empty( $country ) ? wpinv_get_default_country() : $country;
979
    }
980
981
    /**
982
	 * Alias of self::get_country().
983
	 *
984
	 * @since 1.0.19
985
	 * @param  string $context View or edit context.
986
	 * @return int
987
	 */
988
	public function get_user_country( $context = 'view' ) {
989
		return $this->get_country( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_country($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
990
    }
991
992
    /**
993
	 * Alias of self::get_country().
994
	 *
995
	 * @since 1.0.19
996
	 * @param  string $context View or edit context.
997
	 * @return int
998
	 */
999
	public function get_customer_country( $context = 'view' ) {
1000
		return $this->get_country( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_country($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
1001
    }
1002
1003
    /**
1004
	 * Get the customer's state.
1005
	 *
1006
	 * @since 1.0.19
1007
	 * @param  string $context View or edit context.
1008
	 * @return string
1009
	 */
1010
	public function get_state( $context = 'view' ) {
1011
		$state = $this->get_prop( 'state', $context );
1012
		return empty( $state ) ? wpinv_get_default_state() : $state;
0 ignored issues
show
Bug Best Practice introduced by
The expression return empty($state) ? w...efault_state() : $state could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
1013
    }
1014
1015
    /**
1016
	 * Alias of self::get_state().
1017
	 *
1018
	 * @since 1.0.19
1019
	 * @param  string $context View or edit context.
1020
	 * @return int
1021
	 */
1022
	public function get_user_state( $context = 'view' ) {
1023
		return $this->get_state( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_state($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
1024
    }
1025
1026
    /**
1027
	 * Alias of self::get_state().
1028
	 *
1029
	 * @since 1.0.19
1030
	 * @param  string $context View or edit context.
1031
	 * @return int
1032
	 */
1033
	public function get_customer_state( $context = 'view' ) {
1034
		return $this->get_state( $context );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->get_state($context) returns the type string which is incompatible with the documented return type integer.
Loading history...
1035
    }
1036
1037
    /**
1038
	 * Get the customer's city.
1039
	 *
1040
	 * @since 1.0.19
1041
	 * @param  string $context View or edit context.
1042
	 * @return string
1043
	 */
1044
	public function get_city( $context = 'view' ) {
1045
		return $this->get_prop( 'city', $context );
1046
    }
1047
1048
    /**
1049
	 * Alias of self::get_city().
1050
	 *
1051
	 * @since 1.0.19
1052
	 * @param  string $context View or edit context.
1053
	 * @return string
1054
	 */
1055
	public function get_user_city( $context = 'view' ) {
1056
		return $this->get_city( $context );
1057
    }
1058
1059
    /**
1060
	 * Alias of self::get_city().
1061
	 *
1062
	 * @since 1.0.19
1063
	 * @param  string $context View or edit context.
1064
	 * @return string
1065
	 */
1066
	public function get_customer_city( $context = 'view' ) {
1067
		return $this->get_city( $context );
1068
    }
1069
1070
    /**
1071
	 * Get the customer's zip.
1072
	 *
1073
	 * @since 1.0.19
1074
	 * @param  string $context View or edit context.
1075
	 * @return string
1076
	 */
1077
	public function get_zip( $context = 'view' ) {
1078
		return $this->get_prop( 'zip', $context );
1079
    }
1080
1081
    /**
1082
	 * Alias of self::get_zip().
1083
	 *
1084
	 * @since 1.0.19
1085
	 * @param  string $context View or edit context.
1086
	 * @return string
1087
	 */
1088
	public function get_user_zip( $context = 'view' ) {
1089
		return $this->get_zip( $context );
1090
    }
1091
1092
    /**
1093
	 * Alias of self::get_zip().
1094
	 *
1095
	 * @since 1.0.19
1096
	 * @param  string $context View or edit context.
1097
	 * @return string
1098
	 */
1099
	public function get_customer_zip( $context = 'view' ) {
1100
		return $this->get_zip( $context );
1101
    }
1102
1103
    /**
1104
	 * Get the customer's company.
1105
	 *
1106
	 * @since 1.0.19
1107
	 * @param  string $context View or edit context.
1108
	 * @return string
1109
	 */
1110
	public function get_company( $context = 'view' ) {
1111
		return $this->get_prop( 'company', $context );
1112
    }
1113
1114
    /**
1115
	 * Alias of self::get_company().
1116
	 *
1117
	 * @since 1.0.19
1118
	 * @param  string $context View or edit context.
1119
	 * @return string
1120
	 */
1121
	public function get_user_company( $context = 'view' ) {
1122
		return $this->get_company( $context );
1123
    }
1124
1125
    /**
1126
	 * Alias of self::get_company().
1127
	 *
1128
	 * @since 1.0.19
1129
	 * @param  string $context View or edit context.
1130
	 * @return string
1131
	 */
1132
	public function get_customer_company( $context = 'view' ) {
1133
		return $this->get_company( $context );
1134
    }
1135
1136
    /**
1137
	 * Get the customer's vat number.
1138
	 *
1139
	 * @since 1.0.19
1140
	 * @param  string $context View or edit context.
1141
	 * @return string
1142
	 */
1143
	public function get_vat_number( $context = 'view' ) {
1144
		return $this->get_prop( 'vat_number', $context );
1145
    }
1146
1147
    /**
1148
	 * Alias of self::get_vat_number().
1149
	 *
1150
	 * @since 1.0.19
1151
	 * @param  string $context View or edit context.
1152
	 * @return string
1153
	 */
1154
	public function get_user_vat_number( $context = 'view' ) {
1155
		return $this->get_vat_number( $context );
1156
    }
1157
1158
    /**
1159
	 * Alias of self::get_vat_number().
1160
	 *
1161
	 * @since 1.0.19
1162
	 * @param  string $context View or edit context.
1163
	 * @return string
1164
	 */
1165
	public function get_customer_vat_number( $context = 'view' ) {
1166
		return $this->get_vat_number( $context );
1167
    }
1168
1169
    /**
1170
	 * Get the customer's vat rate.
1171
	 *
1172
	 * @since 1.0.19
1173
	 * @param  string $context View or edit context.
1174
	 * @return string
1175
	 */
1176
	public function get_vat_rate( $context = 'view' ) {
1177
		return $this->get_prop( 'vat_rate', $context );
1178
    }
1179
1180
    /**
1181
	 * Alias of self::get_vat_rate().
1182
	 *
1183
	 * @since 1.0.19
1184
	 * @param  string $context View or edit context.
1185
	 * @return string
1186
	 */
1187
	public function get_user_vat_rate( $context = 'view' ) {
1188
		return $this->get_vat_rate( $context );
1189
    }
1190
1191
    /**
1192
	 * Alias of self::get_vat_rate().
1193
	 *
1194
	 * @since 1.0.19
1195
	 * @param  string $context View or edit context.
1196
	 * @return string
1197
	 */
1198
	public function get_customer_vat_rate( $context = 'view' ) {
1199
		return $this->get_vat_rate( $context );
1200
    }
1201
1202
    /**
1203
	 * Get the customer's address.
1204
	 *
1205
	 * @since 1.0.19
1206
	 * @param  string $context View or edit context.
1207
	 * @return string
1208
	 */
1209
	public function get_address( $context = 'view' ) {
1210
		return $this->get_prop( 'address', $context );
1211
    }
1212
1213
    /**
1214
	 * Alias of self::get_address().
1215
	 *
1216
	 * @since 1.0.19
1217
	 * @param  string $context View or edit context.
1218
	 * @return string
1219
	 */
1220
	public function get_user_address( $context = 'view' ) {
1221
		return $this->get_address( $context );
1222
    }
1223
1224
    /**
1225
	 * Alias of self::get_address().
1226
	 *
1227
	 * @since 1.0.19
1228
	 * @param  string $context View or edit context.
1229
	 * @return string
1230
	 */
1231
	public function get_customer_address( $context = 'view' ) {
1232
		return $this->get_address( $context );
1233
    }
1234
1235
    /**
1236
	 * Get whether the customer has viewed the invoice or not.
1237
	 *
1238
	 * @since 1.0.19
1239
	 * @param  string $context View or edit context.
1240
	 * @return bool
1241
	 */
1242
	public function get_is_viewed( $context = 'view' ) {
1243
		return (bool) $this->get_prop( 'is_viewed', $context );
1244
	}
1245
1246
	/**
1247
	 * Get other recipients for invoice communications.
1248
	 *
1249
	 * @since 1.0.19
1250
	 * @param  string $context View or edit context.
1251
	 * @return bool
1252
	 */
1253
	public function get_email_cc( $context = 'view' ) {
1254
		return $this->get_prop( 'email_cc', $context );
1255
	}
1256
1257
	/**
1258
	 * Get invoice template.
1259
	 *
1260
	 * @since 1.0.19
1261
	 * @param  string $context View or edit context.
1262
	 * @return bool
1263
	 */
1264
	public function get_template( $context = 'view' ) {
1265
		return $this->get_prop( 'template', $context );
1266
	}
1267
1268
	/**
1269
	 * Get whether the customer has confirmed their address.
1270
	 *
1271
	 * @since 1.0.19
1272
	 * @param  string $context View or edit context.
1273
	 * @return bool
1274
	 */
1275
	public function get_address_confirmed( $context = 'view' ) {
1276
		return (bool) $this->get_prop( 'address_confirmed', $context );
1277
    }
1278
1279
    /**
1280
	 * Alias of self::get_address_confirmed().
1281
	 *
1282
	 * @since 1.0.19
1283
	 * @param  string $context View or edit context.
1284
	 * @return bool
1285
	 */
1286
	public function get_user_address_confirmed( $context = 'view' ) {
1287
		return $this->get_address_confirmed( $context );
1288
    }
1289
1290
    /**
1291
	 * Alias of self::get_address().
1292
	 *
1293
	 * @since 1.0.19
1294
	 * @param  string $context View or edit context.
1295
	 * @return bool
1296
	 */
1297
	public function get_customer_address_confirmed( $context = 'view' ) {
1298
		return $this->get_address_confirmed( $context );
1299
    }
1300
1301
    /**
1302
	 * Get the invoice subtotal.
1303
	 *
1304
	 * @since 1.0.19
1305
	 * @param  string $context View or edit context.
1306
	 * @return float
1307
	 */
1308
	public function get_subtotal( $context = 'view' ) {
1309
        $subtotal = (float) $this->get_prop( 'subtotal', $context );
1310
1311
        // Backwards compatibility.
1312
        if ( is_bool( $context ) && $context ) {
0 ignored issues
show
introduced by
The condition is_bool($context) is always false.
Loading history...
1313
            return wpinv_price( wpinv_format_amount( $subtotal ), $this->get_currency() );
1314
        }
1315
1316
        return $subtotal;
1317
    }
1318
1319
    /**
1320
	 * Get the invoice discount total.
1321
	 *
1322
	 * @since 1.0.19
1323
	 * @param  string $context View or edit context.
1324
	 * @return float
1325
	 */
1326
	public function get_total_discount( $context = 'view' ) {
1327
		return (float) $this->get_prop( 'total_discount', $context );
1328
    }
1329
1330
    /**
1331
	 * Get the invoice tax total.
1332
	 *
1333
	 * @since 1.0.19
1334
	 * @param  string $context View or edit context.
1335
	 * @return float
1336
	 */
1337
	public function get_total_tax( $context = 'view' ) {
1338
		return (float) $this->get_prop( 'total_tax', $context );
1339
	}
1340
1341
	/**
1342
	 * @deprecated
1343
	 */
1344
	public function get_final_tax( $currency = false ) {
1345
		$tax = $this->get_total_tax();
1346
1347
        if ( $currency ) {
1348
			return wpinv_price( wpinv_format_amount( $tax, NULL, false ), $this->get_currency() );
1349
        }
1350
1351
        return $tax;
1352
    }
1353
1354
    /**
1355
	 * Get the invoice fees total.
1356
	 *
1357
	 * @since 1.0.19
1358
	 * @param  string $context View or edit context.
1359
	 * @return float
1360
	 */
1361
	public function get_total_fees( $context = 'view' ) {
1362
		return (float) $this->get_prop( 'total_fees', $context );
1363
    }
1364
1365
    /**
1366
	 * Alias for self::get_total_fees().
1367
	 *
1368
	 * @since 1.0.19
1369
	 * @param  string $context View or edit context.
1370
	 * @return float
1371
	 */
1372
	public function get_fees_total( $context = 'view' ) {
1373
		return $this->get_total_fees( $context );
1374
    }
1375
1376
    /**
1377
	 * Get the invoice total.
1378
	 *
1379
	 * @since 1.0.19
1380
     * @return float
1381
	 */
1382
	public function get_total() {
1383
		$total = $this->is_renewal() ? $this->get_recurring_total() : $this->get_initial_total();
1384
		return apply_filters( 'getpaid_get_invoice_total_amount', $total, $this  );
1385
    }
1386
1387
    /**
1388
	 * Get the initial invoice total.
1389
	 *
1390
	 * @since 1.0.19
1391
     * @param  string $context View or edit context.
1392
     * @return float
1393
	 */
1394
    public function get_initial_total() {
1395
1396
		if ( empty( $this->totals ) ) {
1397
			$this->recalculate_total();
1398
		}
1399
1400
		$tax      = $this->totals['tax']['initial'];
1401
		$fee      = $this->totals['fee']['initial'];
1402
		$discount = $this->totals['discount']['initial'];
1403
		$subtotal = $this->totals['subtotal']['initial'];
1404
		$total    = $tax + $fee - $discount + $subtotal;
1405
1406
		if ( 0 > $total ) {
1407
			$total = 0;
1408
		}
1409
1410
        return apply_filters( 'wpinv_get_initial_invoice_total', $total, $this );
1411
	}
1412
1413
	/**
1414
	 * Get the recurring invoice total.
1415
	 *
1416
	 * @since 1.0.19
1417
     * @param  string $context View or edit context.
1418
     * @return float
1419
	 */
1420
    public function get_recurring_total() {
1421
1422
		if ( empty( $this->totals ) ) {
1423
			$this->recalculate_total();
1424
		}
1425
1426
		$tax      = $this->totals['tax']['recurring'];
1427
		$fee      = $this->totals['fee']['recurring'];
1428
		$discount = $this->totals['discount']['recurring'];
1429
		$subtotal = $this->totals['subtotal']['recurring'];
1430
		$total    = $tax + $fee - $discount + $subtotal;
1431
1432
		if ( 0 > $total ) {
1433
			$total = 0;
1434
		}
1435
1436
        return apply_filters( 'wpinv_get_recurring_invoice_total', $total, $this );
1437
	}
1438
1439
	/**
1440
	 * Returns recurring payment details.
1441
	 *
1442
	 * @since 1.0.19
1443
     * @param  string $field Optionally provide a field to return.
1444
	 * @param string $currency Whether to include the currency.
1445
     * @return float
1446
	 */
1447
    public function get_recurring_details( $field = '', $currency = false ) {
1448
1449
		// Maybe recalculate totals.
1450
		if ( empty( $this->totals ) ) {
1451
			$this->recalculate_total();
1452
		}
1453
1454
		// Prepare recurring totals.
1455
        $data = apply_filters(
1456
			'wpinv_get_invoice_recurring_details',
1457
			array(
1458
				'cart_details' => $this->get_cart_details(),
1459
				'subtotal'     => $this->totals['subtotal']['recurring'],
1460
				'discount'     => $this->totals['discount']['recurring'],
1461
				'tax'          => $this->totals['tax']['recurring'],
1462
				'fee'          => $this->totals['fee']['recurring'],
1463
				'total'        => $this->get_recurring_total(),
1464
			),
1465
			$this,
1466
			$field,
1467
			$currency
1468
		);
1469
1470
        if ( isset( $data[$field] ) ) {
1471
            return ( $currency ? wpinv_price( $data[$field], $this->get_currency() ) : $data[$field] );
0 ignored issues
show
Bug Best Practice introduced by
The expression return $currency ? wpinv...ency()) : $data[$field] also could return the type string which is incompatible with the documented return type double.
Loading history...
1472
        }
1473
1474
        return $data;
1475
    }
1476
1477
    /**
1478
	 * Get the invoice fees.
1479
	 *
1480
	 * @since 1.0.19
1481
	 * @param  string $context View or edit context.
1482
	 * @return array
1483
	 */
1484
	public function get_fees( $context = 'view' ) {
1485
		return wpinv_parse_list( $this->get_prop( 'fees', $context ) );
1486
    }
1487
1488
    /**
1489
	 * Get the invoice discounts.
1490
	 *
1491
	 * @since 1.0.19
1492
	 * @param  string $context View or edit context.
1493
	 * @return array
1494
	 */
1495
	public function get_discounts( $context = 'view' ) {
1496
		return wpinv_parse_list( $this->get_prop( 'discounts', $context ) );
1497
    }
1498
1499
    /**
1500
	 * Get the invoice taxes.
1501
	 *
1502
	 * @since 1.0.19
1503
	 * @param  string $context View or edit context.
1504
	 * @return array
1505
	 */
1506
	public function get_taxes( $context = 'view' ) {
1507
		return wpinv_parse_list( $this->get_prop( 'taxes', $context ) );
1508
    }
1509
1510
    /**
1511
	 * Get the invoice items.
1512
	 *
1513
	 * @since 1.0.19
1514
	 * @param  string $context View or edit context.
1515
	 * @return GetPaid_Form_Item[]
1516
	 */
1517
	public function get_items( $context = 'view' ) {
1518
        return $this->get_prop( 'items', $context );
1519
    }
1520
1521
    /**
1522
	 * Get the invoice's payment form.
1523
	 *
1524
	 * @since 1.0.19
1525
	 * @param  string $context View or edit context.
1526
	 * @return int
1527
	 */
1528
	public function get_payment_form( $context = 'view' ) {
1529
		return intval( $this->get_prop( 'payment_form', $context ) );
1530
    }
1531
1532
    /**
1533
	 * Get the invoice's submission id.
1534
	 *
1535
	 * @since 1.0.19
1536
	 * @param  string $context View or edit context.
1537
	 * @return string
1538
	 */
1539
	public function get_submission_id( $context = 'view' ) {
1540
		return $this->get_prop( 'submission_id', $context );
1541
    }
1542
1543
    /**
1544
	 * Get the invoice's discount code.
1545
	 *
1546
	 * @since 1.0.19
1547
	 * @param  string $context View or edit context.
1548
	 * @return string
1549
	 */
1550
	public function get_discount_code( $context = 'view' ) {
1551
		return $this->get_prop( 'discount_code', $context );
1552
    }
1553
1554
    /**
1555
	 * Get the invoice's gateway.
1556
	 *
1557
	 * @since 1.0.19
1558
	 * @param  string $context View or edit context.
1559
	 * @return string
1560
	 */
1561
	public function get_gateway( $context = 'view' ) {
1562
		return $this->get_prop( 'gateway', $context );
1563
    }
1564
1565
    /**
1566
	 * Get the invoice's gateway display title.
1567
	 *
1568
	 * @since 1.0.19
1569
	 * @return string
1570
	 */
1571
    public function get_gateway_title() {
1572
        $title =  wpinv_get_gateway_checkout_label( $this->get_gateway() );
1573
        return apply_filters( 'wpinv_gateway_title', $title, $this->get_id(), $this );
1574
    }
1575
1576
    /**
1577
	 * Get the invoice's transaction id.
1578
	 *
1579
	 * @since 1.0.19
1580
	 * @param  string $context View or edit context.
1581
	 * @return string
1582
	 */
1583
	public function get_transaction_id( $context = 'view' ) {
1584
		return $this->get_prop( 'transaction_id', $context );
1585
    }
1586
1587
    /**
1588
	 * Get the invoice's currency.
1589
	 *
1590
	 * @since 1.0.19
1591
	 * @param  string $context View or edit context.
1592
	 * @return string
1593
	 */
1594
	public function get_currency( $context = 'view' ) {
1595
        $currency = $this->get_prop( 'currency', $context );
1596
        return empty( $currency ) ? wpinv_get_currency() : $currency;
1597
    }
1598
1599
    /**
1600
	 * Checks if we are charging taxes for this invoice.
1601
	 *
1602
	 * @since 1.0.19
1603
	 * @param  string $context View or edit context.
1604
	 * @return bool
1605
	 */
1606
	public function get_disable_taxes( $context = 'view' ) {
1607
        return (bool) $this->get_prop( 'disable_taxes', $context );
1608
    }
1609
1610
    /**
1611
	 * Retrieves the subscription id for an invoice.
1612
	 *
1613
	 * @since 1.0.19
1614
	 * @param  string $context View or edit context.
1615
	 * @return int
1616
	 */
1617
    public function get_subscription_id( $context = 'view' ) {
1618
        $subscription_id = $this->get_prop( 'subscription_id', $context );
1619
1620
        if ( empty( $subscription_id ) && $this->is_renewal() ) {
1621
            $parent = $this->get_parent();
1622
            return $parent->get_subscription_id( $context );
1623
        }
1624
1625
        return $subscription_id;
1626
    }
1627
1628
    /**
1629
	 * Retrieves the payment meta for an invoice.
1630
	 *
1631
	 * @since 1.0.19
1632
	 * @param  string $context View or edit context.
1633
	 * @return array
1634
	 */
1635
    public function get_payment_meta( $context = 'view' ) {
1636
1637
        return array(
1638
            'price'        => $this->get_total( $context ),
0 ignored issues
show
Unused Code introduced by
The call to WPInv_Invoice::get_total() has too many arguments starting with $context. ( Ignorable by Annotation )

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

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

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

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

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

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

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

Loading history...
1847
				'from'   => ! empty( $this->status_transition['from'] ) ? $this->status_transition['from'] : $old_status,
1848
				'to'     => $new_status,
1849
				'note'   => $note,
1850
				'manual' => (bool) $manual_update,
1851
			);
1852
1853
			if ( $manual_update ) {
1854
				do_action( 'getpaid_' . $this->object_type .'_edit_status', $this->get_id(), $new_status );
1855
			}
1856
1857
			$this->maybe_set_date_paid();
1858
1859
		}
1860
1861
		return array(
1862
			'from' => $old_status,
1863
			'to'   => $new_status,
1864
		);
1865
	}
1866
1867
	/**
1868
	 * Maybe set date paid.
1869
	 *
1870
	 * Sets the date paid variable when transitioning to the payment complete
1871
	 * order status.
1872
	 *
1873
	 * @since 1.0.19
1874
	 */
1875
	public function maybe_set_date_paid() {
1876
1877
		if ( ! $this->get_date_completed( 'edit' ) && $this->is_paid() ) {
1878
			$this->set_date_completed( current_time( 'mysql' ) );
1879
		}
1880
	}
1881
1882
    /**
1883
	 * Set parent invoice ID.
1884
	 *
1885
	 * @since 1.0.19
1886
	 */
1887
	public function set_parent_id( $value ) {
1888
		if ( $value && ( $value === $this->get_id() ) ) {
1889
			return;
1890
		}
1891
		$this->set_prop( 'parent_id', absint( $value ) );
1892
    }
1893
1894
    /**
1895
	 * Set plugin version when the invoice was created.
1896
	 *
1897
	 * @since 1.0.19
1898
	 */
1899
	public function set_version( $value ) {
1900
		$this->set_prop( 'version', $value );
1901
    }
1902
1903
    /**
1904
	 * Set date when the invoice was created.
1905
	 *
1906
	 * @since 1.0.19
1907
	 * @param string $value Value to set.
1908
     * @return bool Whether or not the date was set.
1909
	 */
1910
	public function set_date_created( $value ) {
1911
        $date = strtotime( $value );
1912
1913
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
1914
            $this->set_prop( 'date_created', date( 'Y-m-d H:i:s', $date ) );
1915
            return true;
1916
        }
1917
1918
        return $this->set_prop( 'date_created', '' );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('date_created', '') targeting GetPaid_Data::set_prop() seems to always return null.

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

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

}

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

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

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

Loading history...
1919
1920
    }
1921
1922
    /**
1923
	 * Set date invoice due date.
1924
	 *
1925
	 * @since 1.0.19
1926
	 * @param string $value Value to set.
1927
     * @return bool Whether or not the date was set.
1928
	 */
1929
	public function set_due_date( $value ) {
1930
        $date = strtotime( $value );
1931
1932
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
1933
            $this->set_prop( 'due_date', date( 'Y-m-d H:i:s', $date ) );
1934
            return true;
1935
        }
1936
1937
		$this->set_prop( 'due_date', '' );
1938
        return false;
1939
1940
    }
1941
1942
    /**
1943
	 * Alias of self::set_due_date().
1944
	 *
1945
	 * @since 1.0.19
1946
	 * @param  string $value New name.
1947
	 */
1948
	public function set_date_due( $value ) {
1949
		$this->set_due_date( $value );
1950
    }
1951
1952
    /**
1953
	 * Set date invoice was completed.
1954
	 *
1955
	 * @since 1.0.19
1956
	 * @param string $value Value to set.
1957
     * @return bool Whether or not the date was set.
1958
	 */
1959
	public function set_completed_date( $value ) {
1960
        $date = strtotime( $value );
1961
1962
        if ( $date && $value !== '0000-00-00 00:00:00'  ) {
1963
            $this->set_prop( 'completed_date', date( 'Y-m-d H:i:s', $date ) );
1964
            return true;
1965
        }
1966
1967
		$this->set_prop( 'completed_date', '' );
1968
        return false;
1969
1970
    }
1971
1972
    /**
1973
	 * Alias of self::set_completed_date().
1974
	 *
1975
	 * @since 1.0.19
1976
	 * @param  string $value New name.
1977
	 */
1978
	public function set_date_completed( $value ) {
1979
		$this->set_completed_date( $value );
1980
    }
1981
1982
    /**
1983
	 * Set date when the invoice was last modified.
1984
	 *
1985
	 * @since 1.0.19
1986
	 * @param string $value Value to set.
1987
     * @return bool Whether or not the date was set.
1988
	 */
1989
	public function set_date_modified( $value ) {
1990
        $date = strtotime( $value );
1991
1992
        if ( $date && $value !== '0000-00-00 00:00:00' ) {
1993
            $this->set_prop( 'date_modified', date( 'Y-m-d H:i:s', $date ) );
1994
            return true;
1995
        }
1996
1997
		$this->set_prop( 'date_modified', '' );
1998
        return false;
1999
2000
    }
2001
2002
    /**
2003
	 * Set the invoice number.
2004
	 *
2005
	 * @since 1.0.19
2006
	 * @param  string $value New number.
2007
	 */
2008
	public function set_number( $value ) {
2009
        $number = sanitize_text_field( $value );
2010
		$this->set_prop( 'number', $number );
2011
    }
2012
2013
    /**
2014
	 * Set the invoice type.
2015
	 *
2016
	 * @since 1.0.19
2017
	 * @param  string $value Type.
2018
	 */
2019
	public function set_type( $value ) {
2020
        $type = sanitize_text_field( str_replace( 'wpi_', '', $value ) );
2021
		$this->set_prop( 'type', $type );
2022
	}
2023
2024
    /**
2025
	 * Set the invoice post type.
2026
	 *
2027
	 * @since 1.0.19
2028
	 * @param  string $value Post type.
2029
	 */
2030
	public function set_post_type( $value ) {
2031
        if ( getpaid_is_invoice_post_type( $value ) ) {
2032
			$this->set_type( $value );
2033
            $this->set_prop( 'post_type', $value );
2034
        }
2035
    }
2036
2037
    /**
2038
	 * Set the invoice key.
2039
	 *
2040
	 * @since 1.0.19
2041
	 * @param  string $value New key.
2042
	 */
2043
	public function set_key( $value ) {
2044
        $key = sanitize_text_field( $value );
2045
		$this->set_prop( 'key', $key );
2046
    }
2047
2048
    /**
2049
	 * Set the invoice mode.
2050
	 *
2051
	 * @since 1.0.19
2052
	 * @param  string $value mode.
2053
	 */
2054
	public function set_mode( $value ) {
2055
        if ( ! in_array( $value, array( 'live', 'test' ) ) ) {
2056
            $this->set_prop( 'value', $value );
2057
        }
2058
    }
2059
2060
    /**
2061
	 * Set the invoice path.
2062
	 *
2063
	 * @since 1.0.19
2064
	 * @param  string $value path.
2065
	 */
2066
	public function set_path( $value ) {
2067
        $this->set_prop( 'path', $value );
2068
    }
2069
2070
    /**
2071
	 * Set the invoice name.
2072
	 *
2073
	 * @since 1.0.19
2074
	 * @param  string $value New name.
2075
	 */
2076
	public function set_name( $value ) {
2077
        $name = sanitize_text_field( $value );
2078
		$this->set_prop( 'name', $name );
2079
    }
2080
2081
    /**
2082
	 * Alias of self::set_name().
2083
	 *
2084
	 * @since 1.0.19
2085
	 * @param  string $value New name.
2086
	 */
2087
	public function set_title( $value ) {
2088
		$this->set_name( $value );
2089
    }
2090
2091
    /**
2092
	 * Set the invoice description.
2093
	 *
2094
	 * @since 1.0.19
2095
	 * @param  string $value New description.
2096
	 */
2097
	public function set_description( $value ) {
2098
        $description = wp_kses_post( $value );
2099
		return $this->set_prop( 'description', $description );
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->set_prop('description', $description) targeting GetPaid_Data::set_prop() seems to always return null.

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

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

}

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

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

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

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

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

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

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

3442
        $this->/** @scrutinizer ignore-call */ 
3443
               save( true );

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

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

Loading history...
3443
        return $this;
3444
    }
3445
3446
    /**
3447
     * Convert this to an array.
3448
     */
3449
    public function array_convert() {
3450
        return $this->get_data();
3451
    }
3452
3453
    /**
3454
     * Adds a note to an invoice.
3455
     *
3456
     * @param string $note The note being added.
3457
     *
3458
     */
3459
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3460
3461
        // Bail if no note specified or this invoice is not yet saved.
3462
        if ( ! $note || $this->get_id() == 0 ) {
3463
            return false;
3464
        }
3465
3466
        if ( ( ( is_user_logged_in() && wpinv_current_user_can_manage_invoicing() ) || $added_by_user ) && !$system ) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (is_user_logged_in() && ...d_by_user) && ! $system, Probably Intended Meaning: is_user_logged_in() && w...d_by_user && ! $system)
Loading history...
3467
            $user                 = get_user_by( 'id', get_current_user_id() );
3468
            $comment_author       = $user->display_name;
3469
            $comment_author_email = $user->user_email;
3470
        } else {
3471
            $comment_author       = 'System';
3472
            $comment_author_email = 'system@';
3473
            $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
3474
            $comment_author_email = sanitize_email( $comment_author_email );
3475
        }
3476
3477
        do_action( 'wpinv_pre_insert_invoice_note', $this->get_id(), $note, $customer_type );
3478
3479
        $note_id = wp_insert_comment( wp_filter_comment( array(
3480
            'comment_post_ID'      => $this->get_id(),
3481
            'comment_content'      => $note,
3482
            'comment_agent'        => 'GetPaid',
3483
            'user_id'              => is_admin() ? get_current_user_id() : 0,
3484
            'comment_date'         => current_time( 'mysql' ),
3485
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
3486
            'comment_approved'     => 1,
3487
            'comment_parent'       => 0,
3488
            'comment_author'       => $comment_author,
3489
            'comment_author_IP'    => wpinv_get_ip(),
3490
            'comment_author_url'   => '',
3491
            'comment_author_email' => $comment_author_email,
3492
            'comment_type'         => 'wpinv_note'
3493
        ) ) );
3494
3495
        do_action( 'wpinv_insert_payment_note', $note_id, $this->get_id(), $note );
3496
3497
        if ( $customer_type ) {
3498
            add_comment_meta( $note_id, '_wpi_customer_note', 1 );
0 ignored issues
show
Bug introduced by
$note_id of type false is incompatible with the type integer expected by parameter $comment_id of add_comment_meta(). ( Ignorable by Annotation )

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

3498
            add_comment_meta( /** @scrutinizer ignore-type */ $note_id, '_wpi_customer_note', 1 );
Loading history...
3499
            do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $this->get_id(), 'user_note' => $note ) );
3500
        }
3501
3502
        return $note_id;
3503
	}
3504
3505
	/**
3506
     * Generates a unique key for the invoice.
3507
     */
3508
    public function generate_key( $string = '' ) {
3509
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3510
        return strtolower(
3511
            md5( $this->get_id() . $string . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3512
        );
3513
    }
3514
3515
    /**
3516
     * Generates a new number for the invoice.
3517
     */
3518
    public function generate_number() {
3519
        $number = $this->get_id();
3520
3521
        if ( $this->has_status( 'auto-draft' ) && wpinv_sequential_number_active( $this->post_type ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
3522
            $number = wpinv_get_next_invoice_number( $this->post_type );
3523
        }
3524
3525
		$number = wpinv_format_invoice_number( $number, $this->post_type );
3526
3527
		return $number;
3528
	}
3529
3530
	/**
3531
	 * Handle the status transition.
3532
	 */
3533
	protected function status_transition() {
3534
		$status_transition = $this->status_transition;
3535
3536
		// Reset status transition variable.
3537
		$this->status_transition = false;
3538
3539
		if ( $status_transition ) {
3540
			try {
3541
3542
				// Fire a hook for the status change.
3543
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this->get_id(), $this, $status_transition );
3544
3545
				// @deprecated this is deprecated and will be removed in the future.
3546
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3547
3548
				if ( ! empty( $status_transition['from'] ) ) {
3549
3550
					/* translators: 1: old invoice status 2: new invoice status */
3551
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'] ), wpinv_status_nicename( $status_transition['to'] ) );
3552
3553
					// Fire another hook.
3554
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
3555
					do_action( 'getpaid_invoice_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
3556
3557
					// @deprecated this is deprecated and will be removed in the future.
3558
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3559
3560
					// Note the transition occurred.
3561
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3562
3563
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3564
					if (
3565
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'wpi-pending', 'wpi-failed', 'wpi-refunded' ), true )
3566
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3567
					) {
3568
						do_action( 'getpaid_invoice_payment_status_changed', $this->get_id(), $this, $status_transition );
3569
					}
3570
				} else {
3571
					/* translators: %s: new invoice status */
3572
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'] ) );
3573
3574
					// Note the transition occurred.
3575
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3576
3577
				}
3578
			} catch ( Exception $e ) {
3579
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
3580
			}
3581
		}
3582
	}
3583
3584
	/**
3585
	 * Updates an invoice status.
3586
	 */
3587
	public function update_status( $new_status = false, $note = '', $manual = false ) {
3588
3589
		// Fires before updating a status.
3590
		do_action( 'wpinv_before_invoice_status_change', $this->get_id(), $new_status, $this->get_status( 'edit' ) );
3591
3592
		// Update the status.
3593
		$this->set_status( $new_status, $note, $manual );
3594
3595
		// Save the order.
3596
		return $this->save();
3597
3598
	}
3599
3600
	/**
3601
	 * @deprecated
3602
	 */
3603
	public function refresh_item_ids() {
3604
        $item_ids = implode( ',', array_unique( array_keys( $this->get_items() ) ) );
3605
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
3606
	}
3607
3608
	/**
3609
	 * @deprecated
3610
	 */
3611
	public function update_items( $temp = false ) {
3612
3613
		$this->set_items( $this->get_items() );
3614
3615
		if ( ! $temp ) {
3616
			$this->save();
3617
		}
3618
3619
        return $this;
3620
	}
3621
3622
	/**
3623
	 * @deprecated
3624
	 */
3625
    public function validate_discount() {
3626
3627
        $discount_code = $this->get_discount_code();
3628
3629
        if ( empty( $discount_code ) ) {
3630
            return false;
3631
        }
3632
3633
        $discount = wpinv_get_discount_obj( $discount_code );
3634
3635
        // Ensure it is active.
3636
        return $discount->exists();
3637
3638
    }
3639
3640
	/**
3641
	 * Refunds an invoice.
3642
	 */
3643
    public function refund() {
3644
		$this->set_status( 'wpi-refunded' );
3645
        $this->save();
3646
    }
3647
3648
	/**
3649
	 * Save data to the database.
3650
	 *
3651
	 * @since 1.0.19
3652
	 * @return int invoice ID
3653
	 */
3654
	public function save() {
3655
		$this->maybe_set_date_paid();
3656
		parent::save();
3657
		$this->status_transition();
3658
		return $this->get_id();
3659
	}
3660
3661
}
3662