Passed
Push — master ( eba4be...60f62d )
by Brian
09:36 queued 04:47
created

WPInv_Invoice::set_discounts()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 4
nc 4
nop 1
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_discount_id_by_code( $invoice, 'key' ) ) {
151
			$this->set_id( $invoice_id );
152
		} elseif ( is_scalar( $invoice ) && $invoice_id = self::get_discount_id_by_code( $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 a discount code, it returns a discount id.
171
	 *
172
	 *
173
	 * @static
174
	 * @param string $discount_code
175
	 * @since 1.0.15
176
	 * @return int
177
	 */
178
	public static function get_discount_id_by_code( $invoice_key_or_number, $field = 'key' ) {
179
        global $wpdb;
180
181
		// Trim the code.
182
        $key = trim( $invoice_key_or_number );
183
184
        // Valid fields.
185
        $fields = array( 'key', 'number' );
186
187
		// Ensure a value has been passed.
188
		if ( empty( $key ) || ! in_array( $field, $fields ) ) {
189
			return 0;
190
		}
191
192
		// Maybe retrieve from the cache.
193
		$invoice_id   = wp_cache_get( $key, 'getpaid_invoice_keys_' . $field );
194
		if ( ! empty( $invoice_id ) ) {
195
			return $invoice_id;
196
		}
197
198
        // Fetch from the db.
199
        $table       = $wpdb->prefix . 'getpaid_invoices';
200
        $invoice_id  = $wpdb->get_var(
201
            $wpdb->prepare( "SELECT `post_id` FROM $table WHERE $field=%s LIMIT 1", $key )
202
        );
203
204
		if ( empty( $invoice_id ) ) {
205
			return 0;
206
		}
207
208
		// Update the cache with our data
209
		wp_cache_set( $key, $invoice_id, 'getpaid_invoice_keys_' . $field );
210
211
		return $invoice_id;
212
    }
213
214
    /**
215
     * Checks if an invoice key is set.
216
     */
217
    public function _isset( $key ) {
218
        return isset( $this->data[$key] ) || method_exists( $this, "get_$key" );
219
    }
220
221
    /*
222
	|--------------------------------------------------------------------------
223
	| CRUD methods
224
	|--------------------------------------------------------------------------
225
	|
226
	| Methods which create, read, update and delete items from the database.
227
	|
228
    */
229
230
    /*
231
	|--------------------------------------------------------------------------
232
	| Getters
233
	|--------------------------------------------------------------------------
234
    */
235
236
    /**
237
	 * Get parent invoice ID.
238
	 *
239
	 * @since 1.0.19
240
	 * @param  string $context View or edit context.
241
	 * @return int
242
	 */
243
	public function get_parent_id( $context = 'view' ) {
244
		return (int) $this->get_prop( 'parent_id', $context );
245
    }
246
247
    /**
248
	 * Get parent invoice.
249
	 *
250
	 * @since 1.0.19
251
	 * @return WPInv_Invoice
252
	 */
253
    public function get_parent_payment() {
254
        return new WPInv_Invoice( $this->get_parent_id() );
255
    }
256
257
    /**
258
	 * Alias for self::get_parent_payment().
259
	 *
260
	 * @since 1.0.19
261
	 * @return WPInv_Invoice
262
	 */
263
    public function get_parent() {
264
        return $this->get_parent_payment();
265
    }
266
267
    /**
268
	 * Get invoice status.
269
	 *
270
	 * @since 1.0.19
271
	 * @param  string $context View or edit context.
272
	 * @return string
273
	 */
274
	public function get_status( $context = 'view' ) {
275
		return $this->get_prop( 'status', $context );
276
    }
277
278
    /**
279
	 * Get invoice status nice name.
280
	 *
281
	 * @since 1.0.19
282
	 * @return string
283
	 */
284
    public function get_status_nicename() {
285
        $statuses = wpinv_get_invoice_statuses( true, true, $this );
286
287
        if ( $this->is_quote() && class_exists( 'Wpinv_Quotes_Shared' ) ) {
288
            $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...
289
        }
290
291
        $status = isset( $statuses[ $this->get_status() ] ) ? $statuses[ $this->get_status() ] : $this->get_status();
292
293
        return apply_filters( 'wpinv_get_invoice_status_nicename', $status );
294
    }
295
296
    /**
297
	 * Get plugin version when the invoice was created.
298
	 *
299
	 * @since 1.0.19
300
	 * @param  string $context View or edit context.
301
	 * @return string
302
	 */
303
	public function get_version( $context = 'view' ) {
304
		return $this->get_prop( 'version', $context );
305
	}
306
307
	/**
308
	 * @deprecated
309
	 */
310
	public function get_invoice_date( $formatted = true ) {
311
        $date_completed = $this->get_date_completed();
312
        $invoice_date   = $date_completed != '0000-00-00 00:00:00' ? $date_completed : '';
313
314
        if ( $invoice_date == '' ) {
315
            $date_created   = $this->get_date_created();
316
            $invoice_date   = $date_created != '0000-00-00 00:00:00' ? $date_created : '';
317
        }
318
319
        if ( $formatted && $invoice_date ) {
320
            $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

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

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

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

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

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