Passed
Push — master ( 60f62d...f597b6 )
by Brian
04:44
created

WPInv_Invoice::get_invoice_id_by_field()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 38
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 17
c 0
b 0
f 0
dl 0
loc 38
rs 9.0777
cc 6
nc 5
nop 2
1
<?php
2
3
// MUST have WordPress.
4
if ( !defined( 'WPINC' ) ) {
5
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
6
}
7
8
/**
9
 * Invoice class.
10
 */
11
class WPInv_Invoice extends GetPaid_Data {
12
13
    /**
14
	 * Which data store to load.
15
	 *
16
	 * @var string
17
	 */
18
    protected $data_store_name = 'invoice';
19
20
    /**
21
	 * This is the name of this object type.
22
	 *
23
	 * @var string
24
	 */
25
    protected $object_type = 'invoice';
26
27
    /**
28
	 * Item Data array. This is the core item data exposed in APIs.
29
	 *
30
	 * @since 1.0.19
31
	 * @var array
32
	 */
33
	protected $data = array(
34
		'parent_id'            => 0,
35
		'status'               => 'wpi-pending',
36
		'version'              => '',
37
		'date_created'         => null,
38
        'date_modified'        => null,
39
        'due_date'             => null,
40
        'completed_date'       => null,
41
        'number'               => '',
42
        'title'                => '',
43
        'path'                 => '',
44
        'key'                  => '',
45
        'description'          => '',
46
        'author'               => 1,
47
        'type'                 => 'invoice',
48
        'post_type'            => 'wpi_invoice',
49
        'mode'                 => 'live',
50
        'user_ip'              => null,
51
        'first_name'           => null,
52
        'last_name'            => null,
53
        'phone'                => null,
54
        'email'                => null,
55
        'country'              => null,
56
        'city'                 => null,
57
        'state'                => null,
58
        'zip'                  => null,
59
        'company'              => null,
60
        'vat_number'           => null,
61
        'vat_rate'             => null,
62
        'address'              => null,
63
        'address_confirmed'    => false,
64
        'subtotal'             => 0,
65
        'total_discount'       => 0,
66
        'total_tax'            => 0,
67
        'total_fees'           => 0,
68
        'fees'                 => array(),
69
        'discounts'            => array(),
70
        'taxes'                => array(),
71
        'items'                => array(),
72
        'payment_form'         => 1,
73
        'submission_id'        => null,
74
        'discount_code'        => null,
75
        'gateway'              => 'none',
76
        'transaction_id'       => '',
77
        'currency'             => '',
78
        'disable_taxes'        => false,
79
		'subscription_id'      => null,
80
		'is_viewed'            => false,
81
		'email_cc'             => '',
82
		'template'             => 'quantity', // hours, amount only
83
    );
84
85
    /**
86
	 * Stores meta in cache for future reads.
87
	 *
88
	 * A group must be set to to enable caching.
89
	 *
90
	 * @var string
91
	 */
92
	protected $cache_group = 'getpaid_invoices';
93
94
    /**
95
     * Stores a reference to the original WP_Post object
96
     *
97
     * @var WP_Post
98
     */
99
    protected $post = null;
100
101
    /**
102
     * Stores a reference to the recurring item id instead of looping through the items.
103
     *
104
     * @var int
105
     */
106
	protected $recurring_item = null;
107
108
	/**
109
     * Stores an array of item totals.
110
	 *
111
	 * e.g $totals['discount'] = array(
112
	 * 		'initial'   => 10,
113
	 * 		'recurring' => 10,
114
	 * )
115
     *
116
     * @var array
117
     */
118
	protected $totals = array();
119
120
	/**
121
	 * Stores the status transition information.
122
	 *
123
	 * @since 1.0.19
124
	 * @var bool
125
	 */
126
	protected $status_transition = false;
127
128
    /**
129
	 * Get the invoice if ID is passed, otherwise the invoice is new and empty.
130
	 *
131
	 * @param  int/string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post $invoice Invoice id, key, number or object to read.
0 ignored issues
show
Documentation Bug introduced by
The doc comment int/string|object|WPInv_..._Legacy_Invoice|WP_Post at position 0 could not be parsed: Unknown type name 'int/string' at position 0 in int/string|object|WPInv_Invoice|WPInv_Legacy_Invoice|WP_Post.
Loading history...
132
	 */
133
    public function __construct( $invoice = false ) {
134
135
        parent::__construct( $invoice );
136
137
		if ( is_numeric( $invoice ) && getpaid_is_invoice_post_type( get_post_type( $invoice ) ) ) {
138
			$this->set_id( $invoice );
139
		} elseif ( $invoice instanceof self ) {
140
			$this->set_id( $invoice->get_id() );
141
		} elseif ( ! empty( $invoice->ID ) ) {
142
			$this->set_id( $invoice->ID );
143
		} elseif ( is_array( $invoice ) ) {
144
			$this->set_props( $invoice );
145
146
			if ( isset( $invoice['ID'] ) ) {
147
				$this->set_id( $invoice['ID'] );
148
			}
149
150
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'key' ) ) {
151
			$this->set_id( $invoice_id );
152
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_invoice_id_by_field( $invoice, 'number' ) ) {
153
			$this->set_id( $invoice_id );
154
		} else {
155
			$this->set_object_read( true );
156
		}
157
158
        // Load the datastore.
159
		$this->data_store = GetPaid_Data_Store::load( $this->data_store_name );
160
161
		if ( $this->get_id() > 0 ) {
162
            $this->post = get_post( $this->get_id() );
163
            $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...
164
			$this->data_store->read( $this );
165
        }
166
167
    }
168
169
    /**
170
	 * Given an invoice key/number, it returns its id.
171
	 *
172
	 *
173
	 * @static
174
	 * @param string $value The invoice key or number
175
	 * @param string $field Either key or number.
176
	 * @since 1.0.15
177
	 * @return int
178
	 */
179
	public static function get_invoice_id_by_field( $value, $field = 'key' ) {
180
        global $wpdb;
181
182
		// Trim the value.
183
		$value = trim( $value );
184
		
185
		if ( empty( $value ) ) {
186
			return 0;
187
		}
188
189
        // Valid fields.
190
        $fields = array( 'key', 'number' );
191
192
		// Ensure a field has been passed.
193
		if ( empty( $field ) || ! in_array( $field, $fields ) ) {
194
			return 0;
195
		}
196
197
		// Maybe retrieve from the cache.
198
		$invoice_id   = wp_cache_get( $field, "getpaid_invoice_{$field}s_to_ids" );
199
		if ( ! empty( $invoice_id ) ) {
200
			return $invoice_id;
201
		}
202
203
        // Fetch from the db.
204
        $table       = $wpdb->prefix . 'getpaid_invoices';
205
        $invoice_id  = $wpdb->get_var(
206
            $wpdb->prepare( "SELECT `post_id` FROM $table WHERE `$field`=%s LIMIT 1", $value )
207
        );
208
209
		if ( empty( $invoice_id ) ) {
210
			return 0;
211
		}
212
213
		// Update the cache with our data
214
		wp_cache_set( $field, $invoice_id, "getpaid_invoice_{$field}s_to_ids" );
215
216
		return $invoice_id;
217
    }
218
219
    /**
220
     * Checks if an invoice key is set.
221
     */
222
    public function _isset( $key ) {
223
        return isset( $this->data[$key] ) || method_exists( $this, "get_$key" );
224
    }
225
226
    /*
227
	|--------------------------------------------------------------------------
228
	| CRUD methods
229
	|--------------------------------------------------------------------------
230
	|
231
	| Methods which create, read, update and delete items from the database.
232
	|
233
    */
234
235
    /*
236
	|--------------------------------------------------------------------------
237
	| Getters
238
	|--------------------------------------------------------------------------
239
    */
240
241
    /**
242
	 * Get parent invoice ID.
243
	 *
244
	 * @since 1.0.19
245
	 * @param  string $context View or edit context.
246
	 * @return int
247
	 */
248
	public function get_parent_id( $context = 'view' ) {
249
		return (int) $this->get_prop( 'parent_id', $context );
250
    }
251
252
    /**
253
	 * Get parent invoice.
254
	 *
255
	 * @since 1.0.19
256
	 * @return WPInv_Invoice
257
	 */
258
    public function get_parent_payment() {
259
        return new WPInv_Invoice( $this->get_parent_id() );
260
    }
261
262
    /**
263
	 * Alias for self::get_parent_payment().
264
	 *
265
	 * @since 1.0.19
266
	 * @return WPInv_Invoice
267
	 */
268
    public function get_parent() {
269
        return $this->get_parent_payment();
270
    }
271
272
    /**
273
	 * Get invoice status.
274
	 *
275
	 * @since 1.0.19
276
	 * @param  string $context View or edit context.
277
	 * @return string
278
	 */
279
	public function get_status( $context = 'view' ) {
280
		return $this->get_prop( 'status', $context );
281
    }
282
283
    /**
284
	 * Get invoice status nice name.
285
	 *
286
	 * @since 1.0.19
287
	 * @return string
288
	 */
289
    public function get_status_nicename() {
290
        $statuses = wpinv_get_invoice_statuses( true, true, $this );
291
292
        if ( $this->is_quote() && class_exists( 'Wpinv_Quotes_Shared' ) ) {
293
            $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...
294
        }
295
296
        $status = isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : $this->get_status();
297
298
        return apply_filters( 'wpinv_get_invoice_status_nicename', $status );
299
    }
300
301
    /**
302
	 * Get plugin version when the invoice was created.
303
	 *
304
	 * @since 1.0.19
305
	 * @param  string $context View or edit context.
306
	 * @return string
307
	 */
308
	public function get_version( $context = 'view' ) {
309
		return $this->get_prop( 'version', $context );
310
	}
311
312
	/**
313
	 * @deprecated
314
	 */
315
	public function get_invoice_date( $formatted = true ) {
316
        $date_completed = $this->get_date_completed();
317
        $invoice_date   = $date_completed != '0000-00-00 00:00:00' ? $date_completed : '';
318
319
        if ( $invoice_date == '' ) {
320
            $date_created   = $this->get_date_created();
321
            $invoice_date   = $date_created != '0000-00-00 00:00:00' ? $date_created : '';
322
        }
323
324
        if ( $formatted && $invoice_date ) {
325
            $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

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

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

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

3385
        $this->/** @scrutinizer ignore-call */ 
3386
               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...
3386
        return $this;
3387
    }
3388
3389
    /**
3390
     * Convert this to an array.
3391
     */
3392
    public function array_convert() {
3393
        return $this->get_data();
3394
    }
3395
3396
    /**
3397
     * Adds a note to an invoice.
3398
     *
3399
     * @param string $note The note being added.
3400
     *
3401
     */
3402
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3403
3404
        // Bail if no note specified or this invoice is not yet saved.
3405
        if ( ! $note || $this->get_id() == 0 ) {
3406
            return false;
3407
        }
3408
3409
        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...
3410
            $user                 = get_user_by( 'id', get_current_user_id() );
3411
            $comment_author       = $user->display_name;
3412
            $comment_author_email = $user->user_email;
3413
        } else {
3414
            $comment_author       = 'System';
3415
            $comment_author_email = 'system@';
3416
            $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
3417
            $comment_author_email = sanitize_email( $comment_author_email );
3418
        }
3419
3420
        do_action( 'wpinv_pre_insert_invoice_note', $this->get_id(), $note, $customer_type );
3421
3422
        $note_id = wp_insert_comment( wp_filter_comment( array(
3423
            'comment_post_ID'      => $this->get_id(),
3424
            'comment_content'      => $note,
3425
            'comment_agent'        => 'GetPaid',
3426
            'user_id'              => is_admin() ? get_current_user_id() : 0,
3427
            'comment_date'         => current_time( 'mysql' ),
3428
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
3429
            'comment_approved'     => 1,
3430
            'comment_parent'       => 0,
3431
            'comment_author'       => $comment_author,
3432
            'comment_author_IP'    => wpinv_get_ip(),
3433
            'comment_author_url'   => '',
3434
            'comment_author_email' => $comment_author_email,
3435
            'comment_type'         => 'wpinv_note'
3436
        ) ) );
3437
3438
        do_action( 'wpinv_insert_payment_note', $note_id, $this->get_id(), $note );
3439
3440
        if ( $customer_type ) {
3441
            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

3441
            add_comment_meta( /** @scrutinizer ignore-type */ $note_id, '_wpi_customer_note', 1 );
Loading history...
3442
            do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $this->get_id(), 'user_note' => $note ) );
3443
        }
3444
3445
        return $note_id;
3446
	}
3447
3448
	/**
3449
     * Generates a unique key for the invoice.
3450
     */
3451
    public function generate_key( $string = '' ) {
3452
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3453
        return strtolower(
3454
            md5( $this->get_id() . $string . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3455
        );
3456
    }
3457
3458
    /**
3459
     * Generates a new number for the invoice.
3460
     */
3461
    public function generate_number() {
3462
        $number = $this->get_id();
3463
3464
        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...
3465
            $next_number = wpinv_get_next_invoice_number( $this->post_type );
3466
            $number      = $next_number;
3467
        }
3468
3469
		$number = wpinv_format_invoice_number( $number, $this->post_type );
3470
3471
		return $number;
3472
	}
3473
3474
	/**
3475
	 * Handle the status transition.
3476
	 */
3477
	protected function status_transition() {
3478
		$status_transition = $this->status_transition;
3479
3480
		// Reset status transition variable.
3481
		$this->status_transition = false;
3482
3483
		if ( $status_transition ) {
3484
			try {
3485
3486
				// Fire a hook for the status change.
3487
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this->get_id(), $this, $status_transition );
3488
3489
				// @deprecated this is deprecated and will be removed in the future.
3490
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3491
3492
				if ( ! empty( $status_transition['from'] ) ) {
3493
3494
					/* translators: 1: old invoice status 2: new invoice status */
3495
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'] ), wpinv_status_nicename( $status_transition['to'] ) );
3496
3497
					// Fire another hook.
3498
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
3499
					do_action( 'getpaid_invoice_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
3500
3501
					// @deprecated this is deprecated and will be removed in the future.
3502
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3503
3504
					// Note the transition occurred.
3505
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3506
3507
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3508
					if (
3509
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'wpi-pending', 'wpi-failed' ), true )
3510
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3511
					) {
3512
						do_action( 'getpaid_invoice_payment_status_changed', $this->get_id(), $this, $status_transition );
3513
					}
3514
				} else {
3515
					/* translators: %s: new invoice status */
3516
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'] ) );
3517
3518
					// Note the transition occurred.
3519
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3520
3521
				}
3522
			} catch ( Exception $e ) {
3523
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
3524
			}
3525
		}
3526
	}
3527
3528
	/**
3529
	 * Updates an invoice status.
3530
	 */
3531
	public function update_status( $new_status = false, $note = '', $manual = false ) {
3532
3533
		// Fires before updating a status.
3534
		do_action( 'wpinv_before_invoice_status_change', $this->get_id(), $new_status, $this->get_status( 'edit' ) );
3535
3536
		// Update the status.
3537
		$this->set_status( $new_status, $note, $manual );
3538
3539
		// Save the order.
3540
		return $this->save();
3541
3542
	}
3543
3544
	/**
3545
	 * @deprecated
3546
	 */
3547
	public function refresh_item_ids() {
3548
        $item_ids = implode( ',', array_unique( array_keys( $this->get_items() ) ) );
3549
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
3550
	}
3551
3552
	/**
3553
	 * @deprecated
3554
	 */
3555
	public function update_items( $temp = false ) {
3556
3557
		$this->set_items( $this->get_items() );
3558
3559
		if ( ! $temp ) {
3560
			$this->save();
3561
		}
3562
3563
        return $this;
3564
	}
3565
3566
	/**
3567
	 * @deprecated
3568
	 */
3569
    public function validate_discount() {
3570
3571
        $discount_code = $this->get_discount_code();
3572
3573
        if ( empty( $discount_code ) ) {
3574
            return false;
3575
        }
3576
3577
        $discount = wpinv_get_discount_obj( $discount_code );
3578
3579
        // Ensure it is active.
3580
        return $discount->exists();
3581
3582
    }
3583
3584
	/**
3585
	 * Refunds an invoice.
3586
	 */
3587
    public function refund() {
3588
		$this->set_status( 'wpi-refunded' );
3589
        $this->save();
3590
    }
3591
3592
	/**
3593
	 * Save data to the database.
3594
	 *
3595
	 * @since 1.0.19
3596
	 * @return int invoice ID
3597
	 */
3598
	public function save() {
3599
		$this->maybe_set_date_paid();
3600
		parent::save();
3601
		$this->status_transition();
3602
		return $this->get_id();
3603
	}
3604
3605
}
3606