Issues (850)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/wpinv-address-functions.php (1 issue)

1
<?php
2
/**
3
 * Contains functions related to Invoicing plugin.
4
 *
5
 * @since 1.0.0
6
 * @package Invoicing
7
 */
8
9
// MUST have WordPress.
10
if ( ! defined( 'WPINC' ) ) {
11
    exit;
12
}
13
14
15
function wpinv_get_default_country() {
16
	$country = wpinv_get_option( 'default_country', 'UK' );
17
18
	return apply_filters( 'wpinv_default_country', $country );
19
}
20
21
/**
22
 * GeoLocates an IP Address.
23
 *
24
 * @return string
25
 */
26
function getpaid_get_ip_country( $ip_address = '' ) {
27
    $country = GetPaid_Geolocation::geolocate_ip( $ip_address, true );
28
    return $country['country'];
29
}
30
31
/**
32
 * Sanitizes a country code.
33
 *
34
 * @param string $country The country code to sanitize
35
 * @return array
36
 */
37
function wpinv_sanitize_country( $country ) {
38
39
	// Enure the country is specified
40
    if ( empty( $country ) ) {
41
        $country = wpinv_get_default_country();
42
    }
43
    return trim( wpinv_utf8_strtoupper( $country ) );
44
45
}
46
47
function wpinv_is_base_country( $country ) {
48
    $base_country = wpinv_get_default_country();
49
50
    if ( $base_country === 'UK' ) {
51
        $base_country = 'GB';
52
    }
53
    if ( $country == 'UK' ) {
54
        $country = 'GB';
55
    }
56
57
    return ( $country && $country === $base_country ) ? true : false;
58
}
59
60
function wpinv_country_name( $country_code = '' ) {
61
    $countries = wpinv_get_country_list();
62
    $country_code = $country_code == 'UK' ? 'GB' : $country_code;
63
    $country = isset( $countries[ $country_code ] ) ? $countries[ $country_code ] : $country_code;
64
65
    return apply_filters( 'wpinv_country_name', $country, $country_code );
66
}
67
68
function wpinv_get_default_state() {
69
	$state = wpinv_get_option( 'default_state', '' );
70
71
	return apply_filters( 'wpinv_default_state', $state );
72
}
73
74
function wpinv_state_name( $state_code = '', $country_code = '' ) {
75
    $state = $state_code;
76
77
    if ( ! empty( $country_code ) ) {
78
        $states = wpinv_get_country_states( $country_code );
79
80
        $state = ! empty( $states ) && isset( $states[ $state_code ] ) ? $states[ $state_code ] : $state;
81
    }
82
83
    return apply_filters( 'wpinv_state_name', $state, $state_code, $country_code );
84
}
85
86
function wpinv_store_address() {
87
    $address = wpinv_get_option( 'store_address', '' );
88
89
    return apply_filters( 'wpinv_store_address', $address );
90
}
91
92
/**
93
 * (Maybe) adds the default address to an invoice.
94
 *
95
 * @param WPInv_Invoice $invoice
96
 */
97
function getpaid_maybe_add_default_address( &$invoice ) {
98
99
    $user_id = $invoice->get_user_id();
100
101
    // Abort if the invoice belongs to no one.
102
    if ( empty( $user_id ) ) {
103
        return;
104
    }
105
106
    // Fill in defaults whenever necessary.
107
    foreach ( wpinv_get_user_address( $user_id ) as $key => $value ) {
108
109
        if ( is_callable( $invoice, "get_$key" ) ) {
110
            $current = call_user_func( array( $invoice, "get_$key" ) );
111
112
            if ( empty( $current ) ) {
113
                $method = "set_$key";
114
                $invoice->$method( $value );
115
            }
116
}
117
}
118
119
}
120
121
/**
122
 * Returns an array of user address fields
123
 *
124
 * @return array
125
 */
126
function getpaid_user_address_fields( $force_vat = false ) {
127
128
    $address_fields = apply_filters(
129
        'getpaid_user_address_fields',
130
        array(
131
            'first_name' => __( 'First Name', 'invoicing' ),
132
            'last_name'  => __( 'Last Name', 'invoicing' ),
133
            'address'    => __( 'Address', 'invoicing' ),
134
            'city'       => __( 'City', 'invoicing' ),
135
            'country'    => __( 'Country', 'invoicing' ),
136
            'state'      => __( 'State', 'invoicing' ),
137
            'zip'        => __( 'Zip/Postal Code', 'invoicing' ),
138
            'phone'      => __( 'Phone Number', 'invoicing' ),
139
            'company'    => __( 'Company', 'invoicing' ),
140
            'company_id' => __( 'Company ID', 'invoicing' ),
141
            'vat_number' => __( 'VAT Number', 'invoicing' ),
142
        )
143
    );
144
145
    if ( ! wpinv_use_taxes() && isset( $address_fields['vat_number'] ) && ! wp_doing_ajax() && ! $force_vat ) {
146
        unset( $address_fields['vat_number'] );
147
    }
148
149
    return $address_fields;
150
}
151
152
/**
153
 * Checks whether or not an address field is whitelisted.
154
 *
155
 * @return bool
156
 */
157
function getpaid_is_address_field_whitelisted( $key ) {
158
    return array_key_exists( $key, getpaid_user_address_fields() );
159
}
160
161
/**
162
 * Saves a user address.
163
 *
164
 * This function is called whenever an invoice is created/updated to ensure that the user address is always up to date.
165
 *
166
 * @param WPInv_Invoice $invoice
167
 */
168
function getpaid_save_invoice_user_address( $invoice ) {
169
170
    // Retrieve the invoice.
171
    $invoice = wpinv_get_invoice( $invoice );
172
173
    // Abort if it does not exist.
174
    if ( empty( $invoice ) || $invoice->is_renewal() ) {
175
        return;
176
    }
177
178
    $customer = getpaid_get_customer_by_user_id( $invoice->get_user_id() );
179
180
    if ( empty( $customer ) ) {
181
        $customer = new GetPaid_Customer( 0 );
182
        $customer->clone_user( $invoice->get_user_id() );
183
    }
184
185
    foreach ( array_keys( getpaid_user_address_fields() ) as $field ) {
186
187
        if ( is_callable( array( $invoice, "get_$field" ) ) ) {
188
            $value = call_user_func( array( $invoice, "get_$field" ) );
189
190
            // Only save if it is not empty.
191
            if ( ! empty( $value ) ) {
192
                $customer->set( $field, sanitize_text_field( $value ) );
193
            }
194
        }
195
    }
196
197
    $customer->save();
198
199
    if ( ! $invoice->get_customer_id() ) {
200
        $invoice->set_customer_id( $customer->get_id() );
201
        $invoice->save();
202
    }
203
}
204
add_action( 'getpaid_new_invoice', 'getpaid_save_invoice_user_address' );
205
add_action( 'getpaid_update_invoice', 'getpaid_save_invoice_user_address' );
206
207
/**
208
 * Retrieves a saved user address.
209
 *
210
 * @param int $user_id The user id whose address we should get. Defaults to the current user id.
211
 * @return array
212
 */
213
function wpinv_get_user_address( $user_id = 0 ) {
214
215
    // Prepare the user id.
216
    $user_id   = empty( $user_id ) ? get_current_user_id() : $user_id;
217
    $user_info = get_userdata( $user_id );
218
219
    // Abort if non exists.
220
    if ( empty( $user_info ) ) {
221
        return array();
222
    }
223
224
    $customer = getpaid_get_customer_by_user_id( $user_id );
225
226
    if ( empty( $customer ) ) {
227
        $customer = new GetPaid_Customer( 0 );
228
        $customer->clone_user( $user_id );
229
    }
230
231
    // Prepare the address.
232
    $address = array(
233
        'user_id'      => $user_id,
234
        'email'        => $customer->get( 'email' ),
235
        'display_name' => $user_info->display_name,
236
    );
237
238
    foreach ( array_keys( getpaid_user_address_fields() ) as $field ) {
239
        $address[ $field ] = $customer->get( $field );
240
    }
241
242
    $address = array_filter( $address );
243
244
    $defaults = array(
245
        'first_name' => $user_info->first_name,
246
        'last_name'  => $user_info->last_name,
247
        'state'      => wpinv_get_default_state(),
248
        'country'    => wpinv_get_default_country(),
249
    );
250
251
    return getpaid_array_merge_if_empty( $address, $defaults );
252
253
}
254
255
/**
256
 * Retrieves a saved user address field.
257
 *
258
 * @param int $user_id The user id whose address field we should get.
259
 * @param string $field The field to use.
260
 * @return string|null
261
 * @deprecated
262
 */
263
function getpaid_get_user_address_field( $user_id, $field ) {
264
265
    $prefixes = array(
266
        '_wpinv_',
267
        'billing_',
268
        '',
269
    );
270
271
    foreach ( $prefixes as $prefix ) {
272
273
        // Meta table.
274
        $value = get_user_meta( $user_id, $prefix . $field, true );
275
276
        // UWP table.
277
        $value = ( empty( $value ) && function_exists( 'uwp_get_usermeta' ) ) ? uwp_get_usermeta( $user_id, $prefix . $field ) : $value;
278
279
        if ( ! empty( $value ) ) {
280
            return $value;
281
        }
282
}
283
284
    return null;
285
286
}
287
288
/**
289
 * Get all continents.
290
 *
291
 * @since 1.0.14
292
 * @param string $return What to return.
293
 * @return array
294
 */
295
function wpinv_get_continents( $return = 'all' ) {
296
297
    $continents = wpinv_get_data( 'continents' );
298
299
    switch ( $return ) {
300
        case 'name':
301
            return wp_list_pluck( $continents, 'name' );
302
            break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
303
        case 'countries':
304
            return wp_list_pluck( $continents, 'countries' );
305
            break;
306
        default:
307
            return $continents;
308
            break;
309
    }
310
311
}
312
313
/**
314
 * Get continent code for a country code.
315
 *
316
 * @since 1.0.14
317
 * @param string $country Country code. If no code is specified, defaults to the default country.
318
 * @return string
319
 */
320
function wpinv_get_continent_code_for_country( $country = false ) {
321
322
    $country = wpinv_sanitize_country( $country );
323
324
	foreach ( wpinv_get_continents( 'countries' ) as $continent_code => $countries ) {
325
		if ( false !== array_search( $country, $countries, true ) ) {
326
			return $continent_code;
327
		}
328
	}
329
330
    return '';
331
332
}
333
334
/**
335
 * Get all calling codes.
336
 *
337
 * @since 1.0.14
338
 * @param string $country Country code. If no code is specified, defaults to the default country.
339
 * @return array
340
 */
341
function wpinv_get_country_calling_code( $country = null ) {
342
343
    $country = wpinv_sanitize_country( $country );
344
    $codes   = wpinv_get_data( 'phone-codes' );
345
    $code    = isset( $codes[ $country ] ) ? $codes[ $country ] : '';
346
347
    if ( is_array( $code ) ) {
348
        return $code[0];
349
    }
350
    return $code;
351
352
}
353
354
/**
355
 * Get all countries.
356
 *
357
 * @param bool $first_empty Whether or not the first item in the list should be empty
358
 * @return array
359
 */
360
function wpinv_get_country_list( $first_empty = false ) {
361
    return wpinv_maybe_add_empty_option( apply_filters( 'wpinv_countries', wpinv_get_data( 'countries' ) ), $first_empty );
362
}
363
364
/**
365
 * Retrieves a given country's states.
366
 *
367
 * @param string $country Country code. If no code is specified, defaults to the default country.
368
 * @param bool $first_empty Whether or not the first item in the list should be empty
369
 * @return array
370
 */
371
function wpinv_get_country_states( $country = null, $first_empty = false ) {
372
373
    // Prepare the country.
374
    $country = wpinv_sanitize_country( $country );
375
376
    // Fetch all states.
377
    $all_states = wpinv_get_data( 'states' );
378
379
    // Fetch the specified country's states.
380
    $states     = isset( $all_states[ $country ] ) ? $all_states[ $country ] : array();
381
    $states     = apply_filters( "wpinv_{$country}_states", $states );
382
    $states     = apply_filters( 'wpinv_country_states', $states, $country );
383
384
    asort( $states );
385
386
    return wpinv_maybe_add_empty_option( $states, $first_empty );
387
}
388
389
/**
390
 * Returns US states.
391
 *
392
 * @deprecated 1.0.14
393
 * @return array
394
 */
395
function wpinv_get_us_states_list() {
396
    return apply_filters( 'wpinv_usa_states', wpinv_get_country_states( 'US' ) );
397
}
398
399
/**
400
 * Returns Canada states.
401
 *
402
 * @deprecated 1.0.14
403
 * @return array
404
 */
405
function wpinv_get_canada_states_list() {
406
    return apply_filters( 'wpinv_canada_provinces', wpinv_get_country_states( 'CA' ) );
407
}
408
409
/**
410
 * Returns australian states.
411
 *
412
 * @deprecated 1.0.14
413
 * @return array
414
 */
415
function wpinv_get_australia_states_list() {
416
    return apply_filters( 'wpinv_australia_states', wpinv_get_country_states( 'AU' ) );
417
}
418
419
/**
420
 * Returns bangladeshi states.
421
 *
422
 * @deprecated 1.0.14
423
 * @return array
424
 */
425
function wpinv_get_bangladesh_states_list() {
426
    return apply_filters( 'wpinv_bangladesh_states', wpinv_get_country_states( 'BD' ) );
427
}
428
429
/**
430
 * Returns brazilianUS states.
431
 *
432
 * @deprecated 1.0.14
433
 * @return array
434
 */
435
function wpinv_get_brazil_states_list() {
436
    return apply_filters( 'wpinv_brazil_states', wpinv_get_country_states( 'BR' ) );
437
}
438
439
/**
440
 * Returns bulgarian states.
441
 *
442
 * @deprecated 1.0.14
443
 * @return array
444
 */
445
function wpinv_get_bulgaria_states_list() {
446
    return apply_filters( 'wpinv_bulgaria_states', wpinv_get_country_states( 'BG' ) );
447
}
448
449
/**
450
 * Returns hong kon states.
451
 *
452
 * @deprecated 1.0.14
453
 * @return array
454
 */
455
function wpinv_get_hong_kong_states_list() {
456
    return apply_filters( 'wpinv_hong_kong_states', wpinv_get_country_states( 'HK' ) );
457
}
458
459
/**
460
 * Returns hungarian states.
461
 *
462
 * @deprecated 1.0.14
463
 * @return array
464
 */
465
function wpinv_get_hungary_states_list() {
466
    return apply_filters( 'wpinv_hungary_states', wpinv_get_country_states( 'HU' ) );
467
}
468
469
/**
470
 * Returns japanese states.
471
 *
472
 * @deprecated 1.0.14
473
 * @return array
474
 */
475
function wpinv_get_japan_states_list() {
476
    return apply_filters( 'wpinv_japan_states', wpinv_get_country_states( 'JP' ) );
477
}
478
479
/**
480
 * Returns chinese states.
481
 *
482
 * @deprecated 1.0.14
483
 * @return array
484
 */
485
function wpinv_get_china_states_list() {
486
    return apply_filters( 'wpinv_china_states', wpinv_get_country_states( 'CN' ) );
487
}
488
489
/**
490
 * Returns new zealand states.
491
 *
492
 * @deprecated 1.0.14
493
 * @return array
494
 */
495
function wpinv_get_new_zealand_states_list() {
496
    return apply_filters( 'wpinv_new_zealand_states', wpinv_get_country_states( 'NZ' ) );
497
}
498
499
/**
500
 * Returns perusian states.
501
 *
502
 * @deprecated 1.0.14
503
 * @return array
504
 */
505
function wpinv_get_peru_states_list() {
506
    return apply_filters( 'wpinv_peru_states', wpinv_get_country_states( 'PE' ) );
507
}
508
509
/**
510
 * Returns indonesian states.
511
 *
512
 * @deprecated 1.0.14
513
 * @return array
514
 */
515
function wpinv_get_indonesia_states_list() {
516
    return apply_filters( 'wpinv_indonesia_states', wpinv_get_country_states( 'ID' ) );
517
}
518
519
/**
520
 * Returns indian states.
521
 *
522
 * @deprecated 1.0.14
523
 * @return array
524
 */
525
function wpinv_get_india_states_list() {
526
    return apply_filters( 'wpinv_india_states', wpinv_get_country_states( 'IN' ) );
527
}
528
529
/**
530
 * Returns iranian states.
531
 *
532
 * @deprecated 1.0.14
533
 * @return array
534
 */
535
function wpinv_get_iran_states_list() {
536
    return apply_filters( 'wpinv_iran_states', wpinv_get_country_states( 'IR' ) );
537
}
538
539
/**
540
 * Returns italian states.
541
 *
542
 * @deprecated 1.0.14
543
 * @return array
544
 */
545
function wpinv_get_italy_states_list() {
546
    return apply_filters( 'wpinv_italy_states', wpinv_get_country_states( 'IT' ) );
547
}
548
549
/**
550
 * Returns malaysian states.
551
 *
552
 * @deprecated 1.0.14
553
 * @return array
554
 */
555
function wpinv_get_malaysia_states_list() {
556
    return apply_filters( 'wpinv_malaysia_states', wpinv_get_country_states( 'MY' ) );
557
}
558
559
/**
560
 * Returns mexican states.
561
 *
562
 * @deprecated 1.0.14
563
 * @return array
564
 */
565
function wpinv_get_mexico_states_list() {
566
    return apply_filters( 'wpinv_mexico_states', wpinv_get_country_states( 'MX' ) );
567
}
568
569
/**
570
 * Returns nepal states.
571
 *
572
 * @deprecated 1.0.14
573
 * @return array
574
 */
575
function wpinv_get_nepal_states_list() {
576
    return apply_filters( 'wpinv_nepal_states', wpinv_get_country_states( 'NP' ) );
577
}
578
579
/**
580
 * Returns south african states.
581
 *
582
 * @deprecated 1.0.14
583
 * @return array
584
 */
585
function wpinv_get_south_africa_states_list() {
586
    return apply_filters( 'wpinv_south_africa_states', wpinv_get_country_states( 'ZA' ) );
587
}
588
589
/**
590
 * Returns thailandese states.
591
 *
592
 * @deprecated 1.0.14
593
 * @return array
594
 */
595
function wpinv_get_thailand_states_list() {
596
    return apply_filters( 'wpinv_thailand_states', wpinv_get_country_states( 'TH' ) );
597
}
598
599
/**
600
 * Returns turkish states.
601
 *
602
 * @deprecated 1.0.14
603
 * @return array
604
 */
605
function wpinv_get_turkey_states_list() {
606
    return apply_filters( 'wpinv_turkey_states', wpinv_get_country_states( 'TR' ) );
607
}
608
609
/**
610
 * Returns spanish states.
611
 *
612
 * @deprecated 1.0.14
613
 * @return array
614
 */
615
function wpinv_get_spain_states_list() {
616
    return apply_filters( 'wpinv_spain_states', wpinv_get_country_states( 'ES' ) );
617
}
618
619
function wpinv_get_states_field() {
620
	if ( empty( $_POST['country'] ) ) {
621
		$_POST['country'] = wpinv_get_default_country();
622
	}
623
	$states = wpinv_get_country_states( sanitize_text_field( $_POST['country'] ) );
624
625
	if ( ! empty( $states ) ) {
626
		$sanitized_field_name = sanitize_text_field( $_POST['field_name'] );
627
628
        $class  = isset( $_POST['class'] ) ? esc_attr( sanitize_text_field( $_POST['class'] ) ) : '';
629
        $class .= " $sanitized_field_name getpaid_js_field-state custom-select wpinv-select wpi_select2";
630
631
        $args  = array(
632
			'name'             => $sanitized_field_name,
633
			'id'               => $sanitized_field_name,
634
			'class'            => implode( ' ', array_unique( explode( ' ', $class ) ) ),
635
			'options'          => array_merge( array( '' => '' ), $states ),
636
			'show_option_all'  => false,
637
			'show_option_none' => false,
638
		);
639
640
		wpinv_html_select( $args );
641
642
	} else {
643
		echo 'nostates';
644
	}
645
646
}
647
648
function wpinv_default_billing_country( $country = '', $user_id = 0 ) {
649
    $country = ! empty( $country ) ? $country : wpinv_get_default_country();
650
651
    return apply_filters( 'wpinv_default_billing_country', $country, $user_id );
652
}
653
654
/**
655
 * Returns country address formats.
656
 *
657
 * These define how addresses are formatted for display in various countries.
658
 *
659
 * @return array
660
 */
661
function wpinv_get_address_formats() {
662
663
		return apply_filters(
664
            'wpinv_localisation_address_formats',
665
			array(
666
				'default' => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}\n{{zip}}\n{{country}}",
667
				'AU'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}} {{zip}}\n{{country}}",
668
				'AT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
669
				'BE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
670
				'CA'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{state_code}}&nbsp;&nbsp;{{zip}}\n{{country}}",
671
				'CH'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
672
				'CL'      => "{{company}}\n{{name}}\n{{address}}\n{{state}}\n{{zip}} {{city}}\n{{country}}",
673
				'CN'      => "{{country}} {{zip}}\n{{state}}, {{city}}, {{address}}\n{{company}}\n{{name}}",
674
				'CZ'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
675
				'DE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
676
				'EE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
677
				'FI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
678
				'DK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
679
				'FR'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city_upper}}\n{{country}}",
680
				'HK'      => "{{company}}\n{{first_name}} {{last_name_upper}}\n{{address}}\n{{city_upper}}\n{{state_upper}}\n{{country}}",
681
				'HU'      => "{{name}}\n{{company}}\n{{city}}\n{{address}}\n{{zip}}\n{{country}}",
682
				'IN'      => "{{company}}\n{{name}}\n{{address}}\n{{city}} {{zip}}\n{{state}}, {{country}}",
683
				'IS'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
684
				'IT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}}\n{{city}}\n{{state_upper}}\n{{country}}",
685
				'JP'      => "{{zip}}\n{{state}} {{city}} {{address}}\n{{company}}\n{{last_name}} {{first_name}}\n{{country}}",
686
				'TW'      => "{{company}}\n{{last_name}} {{first_name}}\n{{address}}\n{{state}}, {{city}} {{zip}}\n{{country}}",
687
				'LI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
688
				'NL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
689
				'NZ'      => "{{name}}\n{{company}}\n{{address}}\n{{city}} {{zip}}\n{{country}}",
690
				'NO'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
691
				'PL'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
692
				'PT'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
693
				'SK'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
694
				'RS'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
695
				'SI'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
696
				'ES'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}}\n{{state}}\n{{country}}",
697
				'SE'      => "{{company}}\n{{name}}\n{{address}}\n{{zip}} {{city}}\n{{country}}",
698
				'TR'      => "{{name}}\n{{company}}\n{{address}}\n{{zip}} {{city}} {{state}}\n{{country}}",
699
				'UG'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{state}}, {{country}}",
700
				'US'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}, {{state_code}} {{zip}}\n{{country}}",
701
				'VN'      => "{{name}}\n{{company}}\n{{address}}\n{{city}}\n{{country}}",
702
			)
703
		);
704
}
705
706
/**
707
 * Retrieves the address format to use on Invoices.
708
 *
709
 * @since 1.0.13
710
 * @see `wpinv_get_invoice_address_replacements`
711
 * @return string
712
 */
713
function wpinv_get_full_address_format( $country = false ) {
714
715
    if ( empty( $country ) ) {
716
        $country = wpinv_get_default_country();
717
    }
718
719
    // Get all formats.
720
	$formats = wpinv_get_address_formats();
721
722
	// Get format for the specified country.
723
	$format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
724
725
    /**
726
	 * Filters the address format to use on Invoices.
727
     *
728
     * New lines will be replaced by a `br` element. Double new lines will be replaced by a paragraph. HTML tags are allowed.
729
	 *
730
	 * @since 1.0.13
731
	 *
732
	 * @param string $format  The address format to use.
733
     * @param string $country The country who's address format is being retrieved.
734
	 */
735
    return apply_filters( 'wpinv_get_full_address_format', $format, $country );
736
}
737
738
/**
739
 * Retrieves the address format replacements to use on Invoices.
740
 *
741
 * @since 1.0.13
742
 * @see `wpinv_get_full_address_format`
743
 * @param array $billing_details customer's billing details
744
 * @return array
745
 */
746
function wpinv_get_invoice_address_replacements( $billing_details ) {
747
748
    $default_args = array(
749
        'address'    => '',
750
        'city'       => '',
751
        'state'      => '',
752
        'country'    => '',
753
        'zip'        => '',
754
        'first_name' => '',
755
		'last_name'  => '',
756
		'company'    => '',
757
    );
758
759
    $args    = map_deep( wp_parse_args( array_filter( $billing_details ), $default_args ), 'trim' );
760
    $state   = $args['state'];
761
    $country = $args['country'];
762
763
    // Handle full country name.
764
    $full_country = empty( $country ) ? $country : wpinv_country_name( $country );
765
766
    // Handle full state name.
767
    $full_state   = ( $country && $state ) ? wpinv_state_name( $state, $country ) : $state;
768
769
    $args['postcode']    = $args['zip'];
770
    $args['name']        = $args['first_name'] . ' ' . $args['last_name'];
771
    $args['state']       = $full_state;
772
    $args['state_code']  = $state;
773
    $args['country']     = $full_country;
774
    $args['country_code'] = $country;
775
776
    /**
777
	 * Filters the address format replacements to use on Invoices.
778
     *
779
	 *
780
	 * @since 1.0.13
781
	 *
782
	 * @param array $replacements  The address replacements to use.
783
     * @param array $billing_details  The billing details to use.
784
	 */
785
    $replacements = apply_filters( 'wpinv_get_invoice_address_replacements', $args, $billing_details );
786
787
    $return = array();
788
789
    foreach ( $replacements as $key => $value ) {
790
        $value  = is_scalar( $value ) ? trim( sanitize_text_field( $value ) ) : '';
791
        $return[ '{{' . $key . '}}' ] = $value;
792
        $return[ '{{' . $key . '_upper}}' ] = wpinv_utf8_strtoupper( $value );
793
    }
794
795
    return $return;
796
797
}
798
799
/**
800
 * Trim white space and commas off a line.
801
 *
802
 * @param  string $line Line.
803
 * @since 1.0.14
804
 * @return string
805
 */
806
function wpinv_trim_formatted_address_line( $line ) {
807
	return trim( $line, ', ' );
808
}
809