Passed
Pull Request — master (#377)
by Brian
05:01
created

WPInv_Invoice::get_recurring()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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

317
            $invoice_date   = date_i18n( /** @scrutinizer ignore-type */ get_option( 'date_format' ), strtotime( $invoice_date ) );
Loading history...
318
        }
319
320
        return apply_filters( 'wpinv_get_invoice_date', $invoice_date, $formatted, $this->ID, $this );
321
    }
322
323
    /**
324
	 * Get date when the invoice was created.
325
	 *
326
	 * @since 1.0.19
327
	 * @param  string $context View or edit context.
328
	 * @return string
329
	 */
330
	public function get_date_created( $context = 'view' ) {
331
		return $this->get_prop( 'date_created', $context );
332
    }
333
334
    /**
335
	 * Get GMT date when the invoice was created.
336
	 *
337
	 * @since 1.0.19
338
	 * @param  string $context View or edit context.
339
	 * @return string
340
	 */
341
	public function get_date_created_gmt( $context = 'view' ) {
342
        $date = $this->get_date_created( $context );
343
344
        if ( $date ) {
345
            $date = get_gmt_from_date( $date );
346
        }
347
		return $date;
348
    }
349
350
    /**
351
	 * Get date when the invoice was last modified.
352
	 *
353
	 * @since 1.0.19
354
	 * @param  string $context View or edit context.
355
	 * @return string
356
	 */
357
	public function get_date_modified( $context = 'view' ) {
358
		return $this->get_prop( 'date_modified', $context );
359
    }
360
361
    /**
362
	 * Get GMT date when the invoice was last modified.
363
	 *
364
	 * @since 1.0.19
365
	 * @param  string $context View or edit context.
366
	 * @return string
367
	 */
368
	public function get_date_modified_gmt( $context = 'view' ) {
369
        $date = $this->get_date_modified( $context );
370
371
        if ( $date ) {
372
            $date = get_gmt_from_date( $date );
373
        }
374
		return $date;
375
    }
376
377
    /**
378
	 * Get the invoice due date.
379
	 *
380
	 * @since 1.0.19
381
	 * @param  string $context View or edit context.
382
	 * @return string
383
	 */
384
	public function get_due_date( $context = 'view' ) {
385
		return $this->get_prop( 'due_date', $context );
386
    }
387
388
    /**
389
	 * Alias for self::get_due_date().
390
	 *
391
	 * @since 1.0.19
392
	 * @param  string $context View or edit context.
393
	 * @return string
394
	 */
395
	public function get_date_due( $context = 'view' ) {
396
		return $this->get_due_date( $context );
397
    }
398
399
    /**
400
	 * Get the invoice GMT due date.
401
	 *
402
	 * @since 1.0.19
403
	 * @param  string $context View or edit context.
404
	 * @return string
405
	 */
406
	public function get_due_date_gmt( $context = 'view' ) {
407
        $date = $this->get_due_date( $context );
408
409
        if ( $date ) {
410
            $date = get_gmt_from_date( $date );
411
        }
412
		return $date;
413
    }
414
415
    /**
416
	 * Alias for self::get_due_date_gmt().
417
	 *
418
	 * @since 1.0.19
419
	 * @param  string $context View or edit context.
420
	 * @return string
421
	 */
422
	public function get_gmt_date_due( $context = 'view' ) {
423
		return $this->get_due_date_gmt( $context );
424
    }
425
426
    /**
427
	 * Get date when the invoice was completed.
428
	 *
429
	 * @since 1.0.19
430
	 * @param  string $context View or edit context.
431
	 * @return string
432
	 */
433
	public function get_completed_date( $context = 'view' ) {
434
		return $this->get_prop( 'completed_date', $context );
435
    }
436
437
    /**
438
	 * Alias for self::get_completed_date().
439
	 *
440
	 * @since 1.0.19
441
	 * @param  string $context View or edit context.
442
	 * @return string
443
	 */
444
	public function get_date_completed( $context = 'view' ) {
445
		return $this->get_completed_date( $context );
446
    }
447
448
    /**
449
	 * Get GMT date when the invoice was was completed.
450
	 *
451
	 * @since 1.0.19
452
	 * @param  string $context View or edit context.
453
	 * @return string
454
	 */
455
	public function get_completed_date_gmt( $context = 'view' ) {
456
        $date = $this->get_completed_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_completed_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_completed_date( $context = 'view' ) {
472
		return $this->get_completed_date_gmt( $context );
473
    }
474
475
    /**
476
	 * Get the invoice number.
477
	 *
478
	 * @since 1.0.19
479
	 * @param  string $context View or edit context.
480
	 * @return string
481
	 */
482
	public function get_number( $context = 'view' ) {
483
        $number = $this->get_prop( 'number', $context );
484
485
        if ( empty( $number ) ) {
486
            $number = $this->generate_number();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $number is correct as $this->generate_number() targeting WPInv_Invoice::generate_number() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

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

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

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

3241
        $this->/** @scrutinizer ignore-call */ 
3242
               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...
3242
        return $this;
3243
    }
3244
3245
    /**
3246
     * Convert this to an array.
3247
     */
3248
    public function array_convert() {
3249
        return $this->get_data();
3250
    }
3251
3252
    /**
3253
     * Adds a note to an invoice.
3254
     *
3255
     * @param string $note The note being added.
3256
     *
3257
     */
3258
    public function add_note( $note = '', $customer_type = false, $added_by_user = false, $system = false ) {
3259
3260
        // Bail if no note specified or this invoice is not yet saved.
3261
        if ( ! $note || $this->get_id() == 0 ) {
3262
            return false;
3263
        }
3264
3265
        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...
3266
            $user                 = get_user_by( 'id', get_current_user_id() );
3267
            $comment_author       = $user->display_name;
3268
            $comment_author_email = $user->user_email;
3269
        } else {
3270
            $comment_author       = 'System';
3271
            $comment_author_email = 'system@';
3272
            $comment_author_email .= isset( $_SERVER['HTTP_HOST'] ) ? str_replace( 'www.', '', $_SERVER['HTTP_HOST'] ) : 'noreply.com';
3273
            $comment_author_email = sanitize_email( $comment_author_email );
3274
        }
3275
3276
        do_action( 'wpinv_pre_insert_invoice_note', $this->get_id(), $note, $customer_type );
3277
3278
        $note_id = wp_insert_comment( wp_filter_comment( array(
3279
            'comment_post_ID'      => $this->get_id(),
3280
            'comment_content'      => $note,
3281
            'comment_agent'        => 'GetPaid',
3282
            'user_id'              => is_admin() ? get_current_user_id() : 0,
3283
            'comment_date'         => current_time( 'mysql' ),
3284
            'comment_date_gmt'     => current_time( 'mysql', 1 ),
3285
            'comment_approved'     => 1,
3286
            'comment_parent'       => 0,
3287
            'comment_author'       => $comment_author,
3288
            'comment_author_IP'    => wpinv_get_ip(),
3289
            'comment_author_url'   => '',
3290
            'comment_author_email' => $comment_author_email,
3291
            'comment_type'         => 'wpinv_note'
3292
        ) ) );
3293
3294
        do_action( 'wpinv_insert_payment_note', $note_id, $this->get_id(), $note );
3295
3296
        if ( $customer_type ) {
3297
            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

3297
            add_comment_meta( /** @scrutinizer ignore-type */ $note_id, '_wpi_customer_note', 1 );
Loading history...
3298
            do_action( 'wpinv_new_customer_note', array( 'invoice_id' => $this->get_id(), 'user_note' => $note ) );
3299
        }
3300
3301
        return $note_id;
3302
	}
3303
3304
	/**
3305
     * Generates a unique key for the invoice.
3306
     */
3307
    public function generate_key( $string = '' ) {
3308
        $auth_key  = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
3309
        return strtolower(
3310
            md5( $this->get_id() . $string . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'wpinv', true ) )
3311
        );
3312
    }
3313
3314
    /**
3315
     * Generates a new number for the invoice.
3316
     */
3317
    public function generate_number() {
3318
        $number = $this->get_id();
3319
3320
        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...
3321
            $next_number = wpinv_get_next_invoice_number( $this->post_type );
3322
            $number      = $next_number;
3323
        }
3324
3325
        $number = wpinv_format_invoice_number( $number, $this->post_type );
0 ignored issues
show
Unused Code introduced by
The assignment to $number is dead and can be removed.
Loading history...
3326
	}
3327
3328
	/**
3329
	 * Handle the status transition.
3330
	 */
3331
	protected function status_transition() {
3332
		$status_transition = $this->status_transition;
3333
3334
		// Reset status transition variable.
3335
		$this->status_transition = false;
3336
3337
		if ( $status_transition ) {
3338
			try {
3339
3340
				// Fire a hook for the status change.
3341
				do_action( 'getpaid_invoice_status_' . $status_transition['to'], $this->get_id(), $this, $status_transition );
3342
3343
				// @deprecated this is deprecated and will be removed in the future.
3344
				do_action( 'wpinv_status_' . $status_transition['to'], $this->get_id(), $status_transition['from'] );
3345
3346
				if ( ! empty( $status_transition['from'] ) ) {
3347
3348
					/* translators: 1: old invoice status 2: new invoice status */
3349
					$transition_note = sprintf( __( 'Status changed from %1$s to %2$s.', 'invoicing' ), wpinv_status_nicename( $status_transition['from'] ), wpinv_status_nicename( $status_transition['to'] ) );
3350
3351
					// Fire another hook.
3352
					do_action( 'getpaid_invoice_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->get_id(), $this );
3353
					do_action( 'getpaid_invoice_status_changed', $this->get_id(), $status_transition['from'], $status_transition['to'], $this );
3354
3355
					// @deprecated this is deprecated and will be removed in the future.
3356
					do_action( 'wpinv_status_' . $status_transition['from'] . '_to_' . $status_transition['to'], $this->ID, $status_transition['from'] );
3357
3358
					// Note the transition occurred.
3359
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3360
3361
					// Work out if this was for a payment, and trigger a payment_status hook instead.
3362
					if (
3363
						in_array( $status_transition['from'], array( 'wpi-cancelled', 'wpi-pending', 'wpi-failed' ), true )
3364
						&& in_array( $status_transition['to'], array( 'publish', 'wpi-processing', 'wpi-renewal' ), true )
3365
					) {
3366
						do_action( 'getpaid_invoice_payment_status_changed', $this->get_id(), $this, $status_transition );
3367
					}
3368
				} else {
3369
					/* translators: %s: new invoice status */
3370
					$transition_note = sprintf( __( 'Status set to %s.', 'invoicing' ), wpinv_status_nicename( $status_transition['to'] ) );
3371
3372
					// Note the transition occurred.
3373
					$this->add_note( trim( $status_transition['note'] . ' ' . $transition_note ), 0, $status_transition['manual'] );
3374
3375
				}
3376
			} catch ( Exception $e ) {
3377
				$this->add_note( __( 'Error during status transition.', 'invoicing' ) . ' ' . $e->getMessage() );
3378
			}
3379
		}
3380
	}
3381
3382
	/**
3383
	 * Updates an invoice status.
3384
	 */
3385
	public function update_status( $new_status = false, $note = '', $manual = false ) {
3386
3387
		// Fires before updating a status.
3388
		do_action( 'wpinv_before_invoice_status_change', $this->ID, $new_status, $this->get_status( 'edit' ) );
3389
3390
		// Update the status.
3391
		$this->set_status( $new_status, $note, $manual );
3392
3393
		// Save the order.
3394
		return $this->save();
3395
3396
	}
3397
3398
	/**
3399
	 * @deprecated
3400
	 */
3401
	public function refresh_item_ids() {
3402
        $item_ids = implode( ',', array_unique( array_keys( $this->get_items() ) ) );
3403
        update_post_meta( $this->get_id(), '_wpinv_item_ids', $item_ids );
3404
	}
3405
3406
	/**
3407
	 * @deprecated
3408
	 */
3409
	public function update_items( $temp = false ) {
3410
3411
		$this->set_items( $this->get_items() );
3412
3413
		if ( ! $temp ) {
3414
			$this->save();
3415
		}
3416
3417
        return $this;
3418
	}
3419
3420
	/**
3421
	 * @deprecated
3422
	 */
3423
    public function validate_discount() {
3424
3425
        $discount_code = $this->get_discount_code();
3426
3427
        if ( empty( $discount_code ) ) {
3428
            return false;
3429
        }
3430
3431
        $discount = wpinv_get_discount_obj( $discount_code );
3432
3433
        // Ensure it is active.
3434
        return $discount->exists();
3435
3436
    }
3437
3438
	/**
3439
	 * Refunds an invoice.
3440
	 */
3441
    public function refund() {
3442
		$this->set_status( 'wpi-refunded' );
3443
        $this->save();
3444
    }
3445
3446
	/**
3447
	 * Save data to the database.
3448
	 *
3449
	 * @since 1.0.19
3450
	 * @return int invoice ID
3451
	 */
3452
	public function save() {
3453
		$this->maybe_set_date_paid();
3454
		parent::save();
3455
		$this->status_transition();
3456
		return $this->get_id();
3457
	}
3458
3459
}
3460