Passed
Pull Request — master (#391)
by Brian
13:22
created

WPInv_Invoice::is_parent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

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

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

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

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

filter:
    dependency_paths: ["lib/*"]

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

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

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

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

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

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

1648
            '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...
1649
            'date'         => $this->get_date_created( $context ),
1650
            'user_email'   => $this->get_email( $context ),
1651
            'invoice_key'  => $this->get_key( $context ),
1652
            'currency'     => $this->get_currency( $context ),
1653
            'items'        => $this->get_items( $context ),
1654
            'user_info'    => $this->get_user_info( $context ),
1655
            'cart_details' => $this->get_cart_details(),
1656
            'status'       => $this->get_status( $context ),
1657
            'fees'         => $this->get_fees( $context ),
1658
            'taxes'        => $this->get_taxes( $context ),
1659
        );
1660
1661
    }
1662
1663
    /**
1664
	 * Retrieves the cart details for an invoice.
1665
	 *
1666
	 * @since 1.0.19
1667
	 * @return array
1668
	 */
1669
    public function get_cart_details() {
1670
        $items        = $this->get_items();
1671
        $cart_details = array();
1672
1673
        foreach ( $items as $item_id => $item ) {
1674
            $cart_details[] = $item->prepare_data_for_saving();
1675
        }
1676
1677
        return $cart_details;
1678
	}
1679
1680
	/**
1681
	 * Retrieves the recurring item.
1682
	 *
1683
	 * @return null|GetPaid_Form_Item|int
1684
	 */
1685
	public function get_recurring( $object = false ) {
1686
1687
		// Are we returning an object?
1688
        if ( $object ) {
1689
            return $this->get_item( $this->recurring_item );
1690
        }
1691
1692
        return $this->recurring_item;
1693
    }
1694
1695
	/**
1696
	 * Retrieves the subscription name.
1697
	 *
1698
	 * @since 1.0.19
1699
	 * @return string
1700
	 */
1701
	public function get_subscription_name() {
1702
1703
		// Retrieve the recurring name
1704
        $item = $this->get_recurring( true );
1705
1706
		// Abort if it does not exist.
1707
        if ( empty( $item ) ) {
1708
            return '';
1709
        }
1710
1711
		// Return the item name.
1712
        return apply_filters( 'wpinv_invoice_get_subscription_name', $item->get_name(), $this );
1713
	}
1714
1715
	/**
1716
	 * Retrieves the view url.
1717
	 *
1718
	 * @since 1.0.19
1719
	 * @return string
1720
	 */
1721
	public function get_view_url() {
1722
        $invoice_url = get_permalink( $this->get_id() );
1723
		$invoice_url = add_query_arg( 'invoice_key', $this->get_key(), $invoice_url );
1724
        return apply_filters( 'wpinv_get_view_url', $invoice_url, $this );
1725
	}
1726
1727
	/**
1728
	 * Retrieves the payment url.
1729
	 *
1730
	 * @since 1.0.19
1731
	 * @return string
1732
	 */
1733
	public function get_checkout_payment_url( $deprecated = false, $secret = false ) {
1734
1735
		// Retrieve the checkout url.
1736
        $pay_url = wpinv_get_checkout_uri();
1737
1738
		// Maybe force ssl.
1739
        if ( is_ssl() ) {
1740
            $pay_url = str_replace( 'http:', 'https:', $pay_url );
1741
        }
1742
1743
		// Add the invoice key.
1744
		$pay_url = add_query_arg( 'invoice_key', $this->get_key(), $pay_url );
1745
1746
		// (Maybe?) add a secret
1747
        if ( $secret ) {
1748
            $pay_url = add_query_arg( array( '_wpipay' => md5( $this->get_user_id() . '::' . $this->get_email() . '::' . $this->get_key() ) ), $pay_url );
0 ignored issues
show
Security Variable Injection introduced by
array('_wpipay' => md5($...:' . $this->get_key())) can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and Data is passed through wpinv_clean()
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 924
  2. array('transaction_id' => wpinv_clean($_POST['x_trans_id']), 'gateway' => $this->id) is assigned to $args
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 923
  3. WPInv_Subscription::add_payment() is called
    in includes/gateways/class-getpaid-authorize-net-gateway.php on line 928
  4. Enters via parameter $args
    in includes/wpinv-subscription.php on line 268
  5. WPInv_Invoice::set_transaction_id() is called
    in includes/wpinv-subscription.php on line 289
  6. Enters via parameter $value
    in includes/class-wpinv-invoice.php on line 2827
  7. GetPaid_Data::set_prop() is called
    in includes/class-wpinv-invoice.php on line 2829
  8. Enters via parameter $value
    in includes/data-stores/class-getpaid-data.php on line 793
  9. Data is passed through maybe_unserialize(), and maybe_unserialize($value) is assigned to property WPInv_Invoice::$data
    in includes/data-stores/class-getpaid-data.php on line 800
  10. Read from property WPInv_Invoice::$data, and array_key_exists($prop, $this->changes) ? $this->changes[$prop] : $this->data[$prop] is assigned to $value
    in includes/data-stores/class-getpaid-data.php on line 850
  11. $value is returned
    in includes/data-stores/class-getpaid-data.php on line 857
  12. $this->get_prop('email', $context) is returned
    in includes/class-wpinv-invoice.php on line 933
  13. Data is passed through md5()
    in includes/class-wpinv-invoice.php on line 1748

Used in variable context

  1. add_query_arg() is called
    in includes/class-wpinv-invoice.php on line 1748
  2. Enters via parameter $args
    in wordpress/wp-includes/functions.php on line 1086
  3. $args[1] is assigned to $uri
    in wordpress/wp-includes/functions.php on line 1091
  4. $uri is assigned to $query
    in wordpress/wp-includes/functions.php on line 1126
  5. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 1129
  6. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4938
  7. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4939

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

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

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

3515
        $this->/** @scrutinizer ignore-call */ 
3516
               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...
3516
        return $this;
3517
    }
3518
3519
    /**
3520
     * Convert this to an array.
3521
     */
3522
    public function array_convert() {
3523
        return $this->get_data();
3524
    }
3525
3526
    /**
3527
     * Adds a note to an invoice.
3528
     *
3529
     * @param string $note The note being added.
3530
     *
3531
     */
3532
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3533
3534
        // Bail if no note specified or this invoice is not yet saved.
3535
        if ( ! $note || $this->get_id() == 0 ) {
3536
            return false;
3537
        }
3538
3539
        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...
3540
            $user                 = get_user_by( 'id', get_current_user_id() );
3541
            $comment_author       = $user->display_name;
3542
            $comment_author_email = $user->user_email;
3543
        } else {
3544
            $comment_author       = 'System';
3545
            $comment_author_email = 'system@';
3546
            $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
3547
            $comment_author_email = sanitize_email( $comment_author_email );
3548
        }
3549
3550
        do_action( 'wpinv_pre_insert_invoice_note', $this->get_id(), $note, $customer_type );
3551
3552
        $note_id = wp_insert_comment( wp_filter_comment( array(
3553
            'comment_post_ID'      => $this->get_id(),
3554
            'comment_content'      => $note,
3555
            'comment_agent'        => 'GetPaid',
3556
            'user_id'              => is_admin() ? get_current_user_id() : 0,
3557
            'comment_date'         => current_time( 'mysql' ),
3558
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
3559
            'comment_approved'     => 1,
3560
            'comment_parent'       => 0,
3561
            'comment_author'       => $comment_author,
3562
            'comment_author_IP'    => wpinv_get_ip(),
3563
            'comment_author_url'   => '',
3564
            'comment_author_email' => $comment_author_email,
3565
            'comment_type'         => 'wpinv_note'
3566
        ) ) );
3567
3568
        do_action( 'wpinv_insert_payment_note', $note_id, $this->get_id(), $note );
3569
3570
        if ( $customer_type ) {
3571
            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

3571
            add_comment_meta( /** @scrutinizer ignore-type */ $note_id, '_wpi_customer_note', 1 );
Loading history...
3572
            do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $this->get_id(), 'user_note' => $note ) );
3573
        }
3574
3575
        return $note_id;
3576
	}
3577
3578
	/**
3579
     * Generates a unique key for the invoice.
3580
     */
3581
    public function generate_key( $string = '' ) {
3582
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3583
        return strtolower(
3584
            $string . md5( $this->get_id() . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3585
        );
3586
    }
3587
3588
    /**
3589
     * Generates a new number for the invoice.
3590
     */
3591
    public function generate_number() {
3592
        $number = $this->get_id();
3593
3594
        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...
3595
            $number = wpinv_get_next_invoice_number( $this->post_type );
3596
        }
3597
3598
		$number = wpinv_format_invoice_number( $number, $this->post_type );
3599
3600
		return $number;
3601
	}
3602
3603
	/**
3604
	 * Handle the status transition.
3605
	 */
3606
	protected function status_transition() {
3607
		$status_transition = $this->status_transition;
3608
3609
		// Reset status transition variable.
3610
		$this->status_transition = false;
3611
3612
		if ( $status_transition ) {
3613
			try {
3614
3615
				// Fire a hook for the status change.
3616
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this->get_id(), $this, $status_transition );
3617
3618
				// @deprecated this is deprecated and will be removed in the future.
3619
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3620
3621
				if ( ! empty( $status_transition['from'] ) ) {
3622
3623
					/* translators: 1: old invoice status 2: new invoice status */
3624
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'] ), wpinv_status_nicename( $status_transition['to'] ) );
3625
3626
					// Fire another hook.
3627
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
3628
					do_action( 'getpaid_invoice_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
3629
3630
					// @deprecated this is deprecated and will be removed in the future.
3631
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3632
3633
					// Note the transition occurred.
3634
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3635
3636
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3637
					if (
3638
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'wpi-pending', 'wpi-failed', 'wpi-refunded' ), true )
3639
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3640
					) {
3641
						do_action( 'getpaid_invoice_payment_status_changed', $this->get_id(), $this, $status_transition );
3642
					}
3643
				} else {
3644
					/* translators: %s: new invoice status */
3645
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'] ) );
3646
3647
					// Note the transition occurred.
3648
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3649
3650
				}
3651
			} catch ( Exception $e ) {
3652
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
3653
			}
3654
		}
3655
	}
3656
3657
	/**
3658
	 * Updates an invoice status.
3659
	 */
3660
	public function update_status( $new_status = false, $note = '', $manual = false ) {
3661
3662
		// Fires before updating a status.
3663
		do_action( 'wpinv_before_invoice_status_change', $this->get_id(), $new_status, $this->get_status( 'edit' ) );
3664
3665
		// Update the status.
3666
		$this->set_status( $new_status, $note, $manual );
3667
3668
		// Save the order.
3669
		return $this->save();
3670
3671
	}
3672
3673
	/**
3674
	 * @deprecated
3675
	 */
3676
	public function refresh_item_ids() {
3677
        $item_ids = implode( ',', array_unique( array_keys( $this->get_items() ) ) );
3678
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
3679
	}
3680
3681
	/**
3682
	 * @deprecated
3683
	 */
3684
	public function update_items( $temp = false ) {
3685
3686
		$this->set_items( $this->get_items() );
3687
3688
		if ( ! $temp ) {
3689
			$this->save();
3690
		}
3691
3692
        return $this;
3693
	}
3694
3695
	/**
3696
	 * @deprecated
3697
	 */
3698
    public function validate_discount() {
3699
3700
        $discount_code = $this->get_discount_code();
3701
3702
        if ( empty( $discount_code ) ) {
3703
            return false;
3704
        }
3705
3706
        $discount = wpinv_get_discount_obj( $discount_code );
3707
3708
        // Ensure it is active.
3709
        return $discount->exists();
3710
3711
    }
3712
3713
	/**
3714
	 * Refunds an invoice.
3715
	 */
3716
    public function refund() {
3717
		$this->set_status( 'wpi-refunded' );
3718
        $this->save();
3719
	}
3720
3721
	/**
3722
	 * Marks an invoice as paid.
3723
	 * 
3724
	 * @param string $transaction_id
3725
	 */
3726
    public function mark_paid( $transaction_id = null, $note = '' ) {
3727
3728
		// Set the transaction id.
3729
		if ( empty( $transaction_id ) ) {
3730
			$transaction_id = $this->generate_key('trans_');
3731
		}
3732
3733
		if ( ! $this->get_transaction_id() ) {
3734
			$this->set_transaction_id( $transaction_id );
3735
		}
3736
3737
		if ( $this->is_paid() && 'wpi-processing' != $this->get_status() ) {
3738
			return $this->save();
3739
		}
3740
3741
		// Set the completed date.
3742
		$this->set_date_completed( current_time( 'mysql' ) );
3743
3744
		// Set the new status.
3745
		if ( $this->is_renewal() ) {
3746
3747
			$_note = sprintf(
3748
				__( 'Renewed via %s', 'invoicing' ),
3749
				$this->get_gateway_title() . empty( $note ) ? '' : " ($note)"
3750
			);
3751
3752
			if ( 'none' == $this->get_gateway() ) {
3753
				$_note = $note;
3754
			}
3755
3756
			$this->set_status( 'wpi-renewal', $_note );
3757
3758
		} else {
3759
3760
			$_note = sprintf(
3761
				__( 'Paid via %s', 'invoicing' ),
3762
				$this->get_gateway_title() . empty( $note ) ? '' : " ($note)"
3763
			);
3764
3765
			if ( 'none' == $this->get_gateway() ) {
3766
				$_note = $note;
3767
			}
3768
3769
			$this->set_status( 'publish',$_note );
3770
3771
		}
3772
3773
		// Set checkout mode.
3774
		$mode = wpinv_is_test_mode( $this->get_gateway() ) ? 'test' : 'live';
3775
		$this->set_mode( $mode );
3776
3777
		// Save the invoice.
3778
        $this->save();
3779
	}
3780
3781
3782
	/**
3783
	 * Save data to the database.
3784
	 *
3785
	 * @since 1.0.19
3786
	 * @return int invoice ID
3787
	 */
3788
	public function save() {
3789
		$this->maybe_set_date_paid();
3790
		parent::save();
3791
		$this->status_transition();
3792
		return $this->get_id();
3793
	}
3794
3795
}
3796