Passed
Pull Request — master (#275)
by Brian
07:08 queued 30s
created

wpinv_checkout_billing_info()   B

Complexity

Conditions 8
Paths 26

Size

Total Lines 83
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 49
nc 26
nop 0
dl 0
loc 83
rs 7.8682
c 2
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
12
}
13
14
if ( !is_admin() ) {
15
    add_filter( 'template_include', 'wpinv_template', 10, 1 );
16
    add_action( 'wpinv_invoice_print_body_start', 'wpinv_display_invoice_top_bar' );
17
    add_action( 'wpinv_invoice_top_bar_left', 'wpinv_invoice_display_left_actions' );
18
    add_action( 'wpinv_invoice_top_bar_right', 'wpinv_invoice_display_right_actions' );
19
}
20
21
function wpinv_template_path() {
22
    return apply_filters( 'wpinv_template_path', wpinv_get_theme_template_dir_name() );
23
}
24
25
function wpinv_display_invoice_top_bar( $invoice ) {
26
    if ( empty( $invoice ) ) {
27
        return;
28
    }
29
    ?>
30
    <div class="row wpinv-top-bar no-print">
31
        <div class="container">
32
            <div class="col-xs-6">
33
                <?php do_action( 'wpinv_invoice_top_bar_left', $invoice );?>
34
            </div>
35
            <div class="col-xs-6 text-right">
36
                <?php do_action( 'wpinv_invoice_top_bar_right', $invoice );?>
37
            </div>
38
        </div>
39
    </div>
40
    <?php
41
}
42
43
function wpinv_invoice_display_left_actions( $invoice ) {
44
    if ( empty( $invoice ) ) {
45
        return; // Exit if invoice is not set.
46
    }
47
    
48
    if ( $invoice->post_type == 'wpi_invoice' ) {
49
        if ( $invoice->needs_payment() ) {
50
            ?> <a class="btn btn-success btn-sm" title="<?php esc_attr_e( 'Pay This Invoice', 'invoicing' ); ?>" href="<?php echo esc_url( $invoice->get_checkout_payment_url() ); ?>"><?php _e( 'Pay For Invoice', 'invoicing' ); ?></a><?php
51
        }
52
    }
53
    do_action('wpinv_invoice_display_left_actions', $invoice);
54
}
55
56
function wpinv_invoice_display_right_actions( $invoice ) {
57
    if ( empty( $invoice ) ) {
58
        return; // Exit if invoice is not set.
59
    }
60
61
    if ( $invoice->post_type == 'wpi_invoice' ) { ?>
62
        <a class="btn btn-primary btn-sm btn-print-invoice" onclick="window.print();" href="javascript:void(0)"><?php _e( 'Print Invoice', 'invoicing' ); ?></a>
63
        <?php if ( is_user_logged_in() ) { ?>
64
        &nbsp;&nbsp;<a class="btn btn-warning btn-sm btn-invoice-history" href="<?php echo esc_url( wpinv_get_history_page_uri() ); ?>"><?php _e( 'Invoice History', 'invoicing' ); ?></a>
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_history_page_uri() can also be of type false; however, parameter $url of esc_url() 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

64
        &nbsp;&nbsp;<a class="btn btn-warning btn-sm btn-invoice-history" href="<?php echo esc_url( /** @scrutinizer ignore-type */ wpinv_get_history_page_uri() ); ?>"><?php _e( 'Invoice History', 'invoicing' ); ?></a>
Loading history...
65
        <?php }
66
    }
67
    do_action('wpinv_invoice_display_right_actions', $invoice);
68
}
69
70
function wpinv_before_invoice_content( $content ) {
71
    global $post;
72
73
    if ( !empty( $post ) && $post->post_type == 'wpi_invoice' && is_singular( 'wpi_invoice' ) && is_main_query() ) {
74
        ob_start();
75
        do_action( 'wpinv_before_invoice_content', $post->ID );
76
        $content = ob_get_clean() . $content;
77
    }
78
79
    return $content;
80
}
81
add_filter( 'the_content', 'wpinv_before_invoice_content' );
82
83
function wpinv_after_invoice_content( $content ) {
84
    global $post;
85
86
    if ( !empty( $post ) && $post->post_type == 'wpi_invoice' && is_singular( 'wpi_invoice' ) && is_main_query() ) {
87
        ob_start();
88
        do_action( 'wpinv_after_invoice_content', $post->ID );
89
        $content .= ob_get_clean();
90
    }
91
92
    return $content;
93
}
94
add_filter( 'the_content', 'wpinv_after_invoice_content' );
95
96
function wpinv_get_templates_dir() {
97
    return WPINV_PLUGIN_DIR . 'templates';
98
}
99
100
function wpinv_get_templates_url() {
101
    return WPINV_PLUGIN_URL . 'templates';
102
}
103
104
function wpinv_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
105
    if ( ! empty( $args ) && is_array( $args ) ) {
106
		extract( $args );
107
	}
108
109
	$located = wpinv_locate_template( $template_name, $template_path, $default_path );
110
	// Allow 3rd party plugin filter template file from their plugin.
111
	$located = apply_filters( 'wpinv_get_template', $located, $template_name, $args, $template_path, $default_path );
112
113
	if ( ! file_exists( $located ) ) {
114
        _doing_it_wrong( __FUNCTION__, sprintf( '<code>%s</code> does not exist.', $located ), '2.1' );
115
		return;
116
	}
117
118
	do_action( 'wpinv_before_template_part', $template_name, $template_path, $located, $args );
119
120
	include( $located );
121
122
	do_action( 'wpinv_after_template_part', $template_name, $template_path, $located, $args );
123
}
124
125
function wpinv_get_template_html( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
126
	ob_start();
127
	wpinv_get_template( $template_name, $args, $template_path, $default_path );
128
	return ob_get_clean();
129
}
130
131
function wpinv_locate_template( $template_name, $template_path = '', $default_path = '' ) {
132
    if ( ! $template_path ) {
133
        $template_path = wpinv_template_path();
134
    }
135
136
    if ( ! $default_path ) {
137
        $default_path = WPINV_PLUGIN_DIR . 'templates/';
138
    }
139
140
    // Look within passed path within the theme - this is priority.
141
    $template = locate_template(
142
        array(
143
            trailingslashit( $template_path ) . $template_name,
144
            $template_name
145
        )
146
    );
147
148
    // Get default templates/
149
    if ( !$template && $default_path ) {
150
        $template = trailingslashit( $default_path ) . $template_name;
151
    }
152
153
    // Return what we found.
154
    return apply_filters( 'wpinv_locate_template', $template, $template_name, $template_path );
155
}
156
157
function wpinv_get_template_part( $slug, $name = null, $load = true ) {
158
	do_action( 'get_template_part_' . $slug, $slug, $name );
159
160
	// Setup possible parts
161
	$templates = array();
162
	if ( isset( $name ) )
163
		$templates[] = $slug . '-' . $name . '.php';
164
	$templates[] = $slug . '.php';
165
166
	// Allow template parts to be filtered
167
	$templates = apply_filters( 'wpinv_get_template_part', $templates, $slug, $name );
168
169
	// Return the part that is found
170
	return wpinv_locate_tmpl( $templates, $load, false );
171
}
172
173
function wpinv_locate_tmpl( $template_names, $load = false, $require_once = true ) {
174
	// No file found yet
175
	$located = false;
176
177
	// Try to find a template file
178
	foreach ( (array)$template_names as $template_name ) {
179
180
		// Continue if template is empty
181
		if ( empty( $template_name ) )
182
			continue;
183
184
		// Trim off any slashes from the template name
185
		$template_name = ltrim( $template_name, '/' );
186
187
		// try locating this template file by looping through the template paths
188
		foreach( wpinv_get_theme_template_paths() as $template_path ) {
189
190
			if( file_exists( $template_path . $template_name ) ) {
191
				$located = $template_path . $template_name;
192
				break;
193
			}
194
		}
195
196
		if( !empty( $located ) ) {
197
			break;
198
		}
199
	}
200
201
	if ( ( true == $load ) && ! empty( $located ) )
202
		load_template( $located, $require_once );
203
204
	return $located;
205
}
206
207
function wpinv_get_theme_template_paths() {
208
	$template_dir = wpinv_get_theme_template_dir_name();
209
210
	$file_paths = array(
211
		1 => trailingslashit( get_stylesheet_directory() ) . $template_dir,
212
		10 => trailingslashit( get_template_directory() ) . $template_dir,
213
		100 => wpinv_get_templates_dir()
214
	);
215
216
	$file_paths = apply_filters( 'wpinv_template_paths', $file_paths );
217
218
	// sort the file paths based on priority
219
	ksort( $file_paths, SORT_NUMERIC );
220
221
	return array_map( 'trailingslashit', $file_paths );
222
}
223
224
function wpinv_get_theme_template_dir_name() {
225
	return trailingslashit( apply_filters( 'wpinv_templates_dir', 'invoicing' ) );
226
}
227
228
function wpinv_checkout_meta_tags() {
229
230
	$pages   = array();
231
	$pages[] = wpinv_get_option( 'success_page' );
232
	$pages[] = wpinv_get_option( 'failure_page' );
233
	$pages[] = wpinv_get_option( 'invoice_history_page' );
234
	$pages[] = wpinv_get_option( 'invoice_subscription_page' );
235
236
	if( !wpinv_is_checkout() && !is_page( $pages ) ) {
237
		return;
238
	}
239
240
	echo '<meta name="robots" content="noindex,nofollow" />' . "\n";
241
}
242
add_action( 'wp_head', 'wpinv_checkout_meta_tags' );
243
244
function wpinv_add_body_classes( $class ) {
245
	$classes = (array)$class;
246
247
	if( wpinv_is_checkout() ) {
248
		$classes[] = 'wpinv-checkout';
249
		$classes[] = 'wpinv-page';
250
	}
251
252
	if( wpinv_is_success_page() ) {
253
		$classes[] = 'wpinv-success';
254
		$classes[] = 'wpinv-page';
255
	}
256
257
	if( wpinv_is_failed_transaction_page() ) {
258
		$classes[] = 'wpinv-failed-transaction';
259
		$classes[] = 'wpinv-page';
260
	}
261
262
	if( wpinv_is_invoice_history_page() ) {
263
		$classes[] = 'wpinv-history';
264
		$classes[] = 'wpinv-page';
265
	}
266
267
	if( wpinv_is_subscriptions_history_page() ) {
268
		$classes[] = 'wpinv-subscription';
269
		$classes[] = 'wpinv-page';
270
	}
271
272
	if( wpinv_is_test_mode() ) {
273
		$classes[] = 'wpinv-test-mode';
274
		$classes[] = 'wpinv-page';
275
	}
276
277
	return array_unique( $classes );
278
}
279
add_filter( 'body_class', 'wpinv_add_body_classes' );
280
281
function wpinv_html_dropdown( $name = 'wpinv_discounts', $selected = 0, $status = '' ) {
282
    $args = array( 'nopaging' => true );
283
284
    if ( ! empty( $status ) )
285
        $args['post_status'] = $status;
286
287
    $discounts = wpinv_get_discounts( $args );
288
    $options   = array();
289
290
    if ( $discounts ) {
291
        foreach ( $discounts as $discount ) {
292
            $options[ absint( $discount->ID ) ] = esc_html( get_the_title( $discount->ID ) );
293
        }
294
    } else {
295
        $options[0] = __( 'No discounts found', 'invoicing' );
296
    }
297
298
    $output = wpinv_html_select( array(
299
        'name'             => $name,
300
        'selected'         => $selected,
301
        'options'          => $options,
302
        'show_option_all'  => false,
303
        'show_option_none' => false,
304
    ) );
305
306
    return $output;
307
}
308
309
function wpinv_html_year_dropdown( $name = 'year', $selected = 0, $years_before = 5, $years_after = 0 ) {
310
    $current     = date( 'Y' );
311
    $start_year  = $current - absint( $years_before );
312
    $end_year    = $current + absint( $years_after );
313
    $selected    = empty( $selected ) ? date( 'Y' ) : $selected;
314
    $options     = array();
315
316
    while ( $start_year <= $end_year ) {
317
        $options[ absint( $start_year ) ] = $start_year;
318
        $start_year++;
319
    }
320
321
    $output = wpinv_html_select( array(
322
        'name'             => $name,
323
        'selected'         => $selected,
324
        'options'          => $options,
325
        'show_option_all'  => false,
326
        'show_option_none' => false
327
    ) );
328
329
    return $output;
330
}
331
332
function wpinv_html_month_dropdown( $name = 'month', $selected = 0 ) {
333
334
    $options = array(
335
        '1'  => __( 'January', 'invoicing' ),
336
        '2'  => __( 'February', 'invoicing' ),
337
        '3'  => __( 'March', 'invoicing' ),
338
        '4'  => __( 'April', 'invoicing' ),
339
        '5'  => __( 'May', 'invoicing' ),
340
        '6'  => __( 'June', 'invoicing' ),
341
        '7'  => __( 'July', 'invoicing' ),
342
        '8'  => __( 'August', 'invoicing' ),
343
        '9'  => __( 'September', 'invoicing' ),
344
        '10' => __( 'October', 'invoicing' ),
345
        '11' => __( 'November', 'invoicing' ),
346
        '12' => __( 'December', 'invoicing' ),
347
    );
348
349
    // If no month is selected, default to the current month
350
    $selected = empty( $selected ) ? date( 'n' ) : $selected;
351
352
    $output = wpinv_html_select( array(
353
        'name'             => $name,
354
        'selected'         => $selected,
355
        'options'          => $options,
356
        'show_option_all'  => false,
357
        'show_option_none' => false
358
    ) );
359
360
    return $output;
361
}
362
363
function wpinv_html_select( $args = array() ) {
364
    $defaults = array(
365
        'options'          => array(),
366
        'name'             => null,
367
        'class'            => '',
368
        'id'               => '',
369
        'selected'         => 0,
370
        'placeholder'      => null,
371
        'multiple'         => false,
372
        'show_option_all'  => _x( 'All', 'all dropdown items', 'invoicing' ),
373
        'show_option_none' => _x( 'None', 'no dropdown items', 'invoicing' ),
374
        'data'             => array(),
375
        'onchange'         => null,
376
        'required'         => false,
377
        'disabled'         => false,
378
        'readonly'         => false,
379
    );
380
381
    $args = wp_parse_args( $args, $defaults );
0 ignored issues
show
Security Variable Injection introduced by
$args can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

3 paths for user data to reach this point

  1. Path: Read from $_POST in includes/wpinv-invoice-functions.php on line 1740
  1. Read from $_POST
    in includes/wpinv-invoice-functions.php on line 1740
  2. array('invoice_id' => ! empty($invoice) ? $invoice->ID : 0, 'items' => $cart_items, 'cart_discounts' => $discounts, 'fees' => wpinv_get_cart_fees(), 'subtotal' => wpinv_get_cart_subtotal($cart_items), 'discount' => wpinv_get_cart_items_discount_amount($cart_items, $discounts), 'tax' => wpinv_get_cart_tax($cart_items), 'price' => wpinv_get_cart_total($cart_items, $discounts), 'invoice_key' => $invoice->get_key() ? $invoice->get_key() : $invoice->generate_key(), 'user_email' => $invoice->get_email(), 'date' => date('Y-m-d H:i:s', current_time('timestamp')), 'user_info' => stripslashes_deep($user_info), 'post_data' => $_POST, 'cart_details' => $cart_items, 'gateway' => $valid_data['gateway'], 'card_info' => $valid_data['cc_info']) is assigned to $invoice_data
    in includes/wpinv-invoice-functions.php on line 1727
  3. WPInv_Invoice::set() is called
    in includes/wpinv-invoice-functions.php on line 1763
  4. Enters via parameter $value
    in includes/class-wpinv-invoice.php on line 86
  5. $value is assigned to property WPInv_Invoice::$user_info
    in includes/class-wpinv-invoice.php on line 100
  6. Read from property WPInv_Invoice::$user_info, and $this->user_info['state'] is assigned to property WPInv_Invoice::$state
    in includes/class-wpinv-invoice.php on line 184
  7. Read from property WPInv_Invoice::$state
    in includes/admin/meta-boxes/class-mb-invoice-address.php on line 113
  8. wpinv_html_select() is called
    in includes/admin/meta-boxes/class-mb-invoice-address.php on line 109
  9. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 363
  2. Path: Read from $_GET in includes/admin/wpinv-admin-functions.php on line 363
  1. Read from $_GET
    in includes/admin/wpinv-admin-functions.php on line 363
  2. wpinv_html_select() is called
    in includes/admin/wpinv-admin-functions.php on line 359
  3. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 363
  3. Path: Read from $_GET, and $_GET['vat_class'] is assigned to $class in includes/admin/wpinv-admin-functions.php on line 378
  1. Read from $_GET, and $_GET['vat_class'] is assigned to $class
    in includes/admin/wpinv-admin-functions.php on line 378
  2. wpinv_html_select() is called
    in includes/admin/wpinv-admin-functions.php on line 381
  3. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 363

Used in variable context

  1. wp_parse_args() is called
    in includes/wpinv-template-functions.php on line 381
  2. Enters via parameter $args
    in wordpress/wp-includes/functions.php on line 4294
  3. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 4300
  4. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4865
  5. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4866

General Strategies to prevent injection

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

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

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

$sanitized = (integer) $tainted;
Loading history...
382
383
    if ( isset( $args['field_required'] ) ) {
384
        $args['required'] = $args['field_required'];
385
    }
386
387
    $data_elements = '';
388
    foreach ( $args['data'] as $key => $value ) {
389
        $data_elements .= ' data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
390
    }
391
392
    if( $args['multiple'] ) {
393
        $multiple = ' MULTIPLE';
394
    } else {
395
        $multiple = '';
396
    }
397
398
    if( $args['placeholder'] ) {
399
        $placeholder = $args['placeholder'];
400
    } else {
401
        $placeholder = '';
402
    }
403
    
404
    $options = '';
405
    if( !empty( $args['onchange'] ) ) {
406
        $options .= ' onchange="' . esc_attr( $args['onchange'] ) . '"';
407
    }
408
    
409
    if( !empty( $args['required'] ) ) {
410
        $options .= ' required="required"';
411
    }
412
    
413
    if( !empty( $args['disabled'] ) ) {
414
        $options .= ' disabled';
415
    }
416
    
417
    if( !empty( $args['readonly'] ) ) {
418
        $options .= ' readonly';
419
    }
420
421
    $class  = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
422
    $output = '<select name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" class="wpinv-select ' . $class . '"' . $multiple . ' data-placeholder="' . $placeholder . '" ' . trim( $options ) . $data_elements . '>';
423
424
    if ( $args['show_option_all'] ) {
425
        if( $args['multiple'] ) {
426
            $selected = selected( true, in_array( 0, $args['selected'] ), false );
427
        } else {
428
            $selected = selected( $args['selected'], 0, false );
429
        }
430
        $output .= '<option value="all"' . $selected . '>' . esc_html( $args['show_option_all'] ) . '</option>';
431
    }
432
433
    if ( !empty( $args['options'] ) ) {
434
435
        if ( $args['show_option_none'] ) {
436
            if( $args['multiple'] ) {
437
                $selected = selected( true, in_array( "", $args['selected'] ), false );
438
            } else {
439
                $selected = selected( $args['selected'] === "", true, false );
440
            }
441
            $output .= '<option value=""' . $selected . '>' . esc_html( $args['show_option_none'] ) . '</option>';
442
        }
443
444
        foreach( $args['options'] as $key => $option ) {
445
446
            if( $args['multiple'] && is_array( $args['selected'] ) ) {
447
                $selected = selected( true, (bool)in_array( $key, $args['selected'] ), false );
448
            } else {
449
                $selected = selected( $args['selected'], $key, false );
450
            }
451
452
            $output .= '<option value="' . esc_attr( $key ) . '"' . $selected . '>' . esc_html( $option ) . '</option>';
453
        }
454
    }
455
456
    $output .= '</select>';
457
458
    return $output;
459
}
460
461
/**
462
 * Renders a state select/input field.
463
 */
464
function wpinv_html_state_select( $args = array() ) {
465
466
    $selected_country = empty( $args[ 'country' ] ) ? wpinv_default_billing_country() : $args[ 'country' ];
467
468
    if ( ! empty( $args['billing_details'] ) && ! empty( $args['billing_details']['country'] ) ) {
469
        $selected_country = $args['billing_details']['country'];
470
    }
471
472
    $states = wpinv_get_country_states( $selected_country );
473
474
    if( !empty( $states ) ) {
475
        return wpinv_html_select( array(
476
            'options'          => $states,
477
            'name'             => $args['name'],
478
            'id'               => $args['id'],
479
            'selected'         => $args['value'],
480
            'show_option_all'  => false,
481
            'show_option_none' => false,
482
            'class'            => 'wpi-input form-control wpi_select2',
483
            'placeholder'      => $args['placeholder'],
484
            'required'         => $args['field_required'],
485
        ) );
486
    }
487
488
    return wpinv_html_text( array(
489
            'name'          => $args['name'],
490
            'value'         => $args['value'],
491
            'id'            => $args['id'],
492
            'class'         => 'wpi-input form-control',
493
            'placeholder'   => $args['placeholder'],
494
            'required'      => $args['field_required'],
495
        ) );
496
497
}
498
499
/**
500
 * Renders a country select field.
501
 */
502
function wpinv_html_country_select( $args = array() ) {
503
504
    return wpinv_html_select( array(
505
        'options'          => wpinv_get_country_list(),
506
        'name'             => $args['name'],
507
        'id'               => $args['id'],
508
        'selected'         => $args['value'],
509
        'show_option_all'  => false,
510
        'show_option_none' => false,
511
        'class'            => $args['class'],
512
        'placeholder'      => $args['placeholder'],
513
        'required'         => $args['field_required'],
514
    ) );
515
516
}
517
518
function wpinv_item_dropdown( $args = array() ) {
519
    $defaults = array(
520
        'name'              => 'wpi_item',
521
        'id'                => 'wpi_item',
522
        'class'             => '',
523
        'multiple'          => false,
524
        'selected'          => 0,
525
        'number'            => 100,
526
        'placeholder'       => __( 'Choose a item', 'invoicing' ),
527
        'data'              => array( 'search-type' => 'item' ),
528
        'show_option_all'   => false,
529
        'show_option_none'  => false,
530
        'show_recurring'    => false,
531
    );
532
533
    $args = wp_parse_args( $args, $defaults );
534
535
    $item_args = array(
536
        'post_type'      => 'wpi_item',
537
        'orderby'        => 'title',
538
        'order'          => 'ASC',
539
        'posts_per_page' => $args['number']
540
    );
541
    
542
    $item_args  = apply_filters( 'wpinv_item_dropdown_query_args', $item_args, $args, $defaults );
543
544
    $items      = get_posts( $item_args );
545
    $options    = array();
546
    if ( $items ) {
547
        foreach ( $items as $item ) {
548
            $title = esc_html( $item->post_title );
549
            
550
            if ( !empty( $args['show_recurring'] ) ) {
551
                $title .= wpinv_get_item_suffix( $item->ID, false );
552
            }
553
            
554
            $options[ absint( $item->ID ) ] = $title;
555
        }
556
    }
557
558
    // This ensures that any selected items are included in the drop down
559
    if( is_array( $args['selected'] ) ) {
560
        foreach( $args['selected'] as $item ) {
561
            if( ! in_array( $item, $options ) ) {
562
                $title = get_the_title( $item );
563
                if ( !empty( $args['show_recurring'] ) ) {
564
                    $title .= wpinv_get_item_suffix( $item, false );
565
                }
566
                $options[$item] = $title;
567
            }
568
        }
569
    } elseif ( is_numeric( $args['selected'] ) && $args['selected'] !== 0 ) {
570
        if ( ! in_array( $args['selected'], $options ) ) {
571
            $title = get_the_title( $args['selected'] );
572
            if ( !empty( $args['show_recurring'] ) ) {
573
                $title .= wpinv_get_item_suffix( $args['selected'], false );
574
            }
575
            $options[$args['selected']] = get_the_title( $args['selected'] );
576
        }
577
    }
578
579
    $output = wpinv_html_select( array(
580
        'name'             => $args['name'],
581
        'selected'         => $args['selected'],
582
        'id'               => $args['id'],
583
        'class'            => $args['class'],
584
        'options'          => $options,
585
        'multiple'         => $args['multiple'],
586
        'placeholder'      => $args['placeholder'],
587
        'show_option_all'  => $args['show_option_all'],
588
        'show_option_none' => $args['show_option_none'],
589
        'data'             => $args['data'],
590
    ) );
591
592
    return $output;
593
}
594
595
function wpinv_html_checkbox( $args = array() ) {
596
    $defaults = array(
597
        'name'     => null,
598
        'current'  => null,
599
        'class'    => 'wpinv-checkbox',
600
        'options'  => array(
601
            'disabled' => false,
602
            'readonly' => false
603
        )
604
    );
605
606
    $args = wp_parse_args( $args, $defaults );
607
608
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
609
    $options = '';
610
    if ( ! empty( $args['options']['disabled'] ) ) {
611
        $options .= ' disabled="disabled"';
612
    } elseif ( ! empty( $args['options']['readonly'] ) ) {
613
        $options .= ' readonly';
614
    }
615
616
    $output = '<input type="checkbox"' . $options . ' name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['name'] ) . '" class="' . $class . ' ' . esc_attr( $args['name'] ) . '" ' . checked( 1, $args['current'], false ) . ' />';
617
618
    return $output;
619
}
620
621
function wpinv_html_text( $args = array() ) {
622
    // Backwards compatibility
623
    if ( func_num_args() > 1 ) {
624
        $args = func_get_args();
625
626
        $name  = $args[0];
627
        $value = isset( $args[1] ) ? $args[1] : '';
628
        $label = isset( $args[2] ) ? $args[2] : '';
629
        $desc  = isset( $args[3] ) ? $args[3] : '';
630
    }
631
632
    $defaults = array(
633
        'id'           => '',
634
        'name'         => isset( $name )  ? $name  : 'text',
635
        'value'        => isset( $value ) ? $value : null,
636
        'label'        => isset( $label ) ? $label : null,
637
        'desc'         => isset( $desc )  ? $desc  : null,
638
        'placeholder'  => '',
639
        'class'        => 'regular-text',
640
        'disabled'     => false,
641
        'readonly'     => false,
642
        'required'     => false,
643
        'autocomplete' => '',
644
        'data'         => false
645
    );
646
647
    $args = wp_parse_args( $args, $defaults );
0 ignored issues
show
Security Variable Injection introduced by
$args can contain request data and is used in variable name context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in includes/wpinv-invoice-functions.php on line 1740
  2. array('invoice_id' => ! empty($invoice) ? $invoice->ID : 0, 'items' => $cart_items, 'cart_discounts' => $discounts, 'fees' => wpinv_get_cart_fees(), 'subtotal' => wpinv_get_cart_subtotal($cart_items), 'discount' => wpinv_get_cart_items_discount_amount($cart_items, $discounts), 'tax' => wpinv_get_cart_tax($cart_items), 'price' => wpinv_get_cart_total($cart_items, $discounts), 'invoice_key' => $invoice->get_key() ? $invoice->get_key() : $invoice->generate_key(), 'user_email' => $invoice->get_email(), 'date' => date('Y-m-d H:i:s', current_time('timestamp')), 'user_info' => stripslashes_deep($user_info), 'post_data' => $_POST, 'cart_details' => $cart_items, 'gateway' => $valid_data['gateway'], 'card_info' => $valid_data['cc_info']) is assigned to $invoice_data
    in includes/wpinv-invoice-functions.php on line 1727
  3. WPInv_Invoice::set() is called
    in includes/wpinv-invoice-functions.php on line 1763
  4. Enters via parameter $value
    in includes/class-wpinv-invoice.php on line 86
  5. $value is assigned to property WPInv_Invoice::$user_info
    in includes/class-wpinv-invoice.php on line 100
  6. Read from property WPInv_Invoice::$user_info, and $this->user_info['state'] is assigned to property WPInv_Invoice::$state
    in includes/class-wpinv-invoice.php on line 184
  7. Read from property WPInv_Invoice::$state
    in includes/admin/meta-boxes/class-mb-invoice-address.php on line 123
  8. wpinv_html_text() is called
    in includes/admin/meta-boxes/class-mb-invoice-address.php on line 121
  9. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 621

Used in variable context

  1. wp_parse_args() is called
    in includes/wpinv-template-functions.php on line 647
  2. Enters via parameter $args
    in wordpress/wp-includes/functions.php on line 4294
  3. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 4300
  4. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4865
  5. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4866

General Strategies to prevent injection

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

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

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

$sanitized = (integer) $tainted;
Loading history...
648
649
    if ( isset( $args['field_required'] ) ) {
650
        $args['required'] = $args['field_required'];
651
    }
652
653
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
654
    $options = '';
655
    if( $args['required'] ) {
656
        $options .= ' required="required"';
657
    }
658
    if( $args['readonly'] ) {
659
        $options .= ' readonly';
660
    }
661
    if( $args['readonly'] ) {
662
        $options .= ' readonly';
663
    }
664
665
    $data = '';
666
    if ( !empty( $args['data'] ) ) {
667
        foreach ( $args['data'] as $key => $value ) {
668
            $data .= 'data-' . wpinv_sanitize_key( $key ) . '="' . esc_attr( $value ) . '" ';
669
        }
670
    }
671
672
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
673
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['id'] ) . '">' . esc_html( $args['label'] ) . '</label>';
674
    if ( ! empty( $args['desc'] ) ) {
675
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
676
    }
677
678
    $output .= '<input type="text" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] )  . '" autocomplete="' . esc_attr( $args['autocomplete'] )  . '" value="' . esc_attr( $args['value'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" class="' . $class . '" ' . $data . ' ' . trim( $options ) . '/>';
679
680
    $output .= '</span>';
681
682
    return $output;
683
}
684
685
function wpinv_html_date_field( $args = array() ) {
686
    if( empty( $args['class'] ) ) {
687
        $args['class'] = 'wpiDatepicker';
688
    } elseif( ! strpos( $args['class'], 'wpiDatepicker' ) ) {
689
        $args['class'] .= ' wpiDatepicker';
690
    }
691
692
    return wpinv_html_text( $args );
693
}
694
695
function wpinv_html_textarea( $args = array() ) {
696
    $defaults = array(
697
        'name'        => 'textarea',
698
        'value'       => null,
699
        'label'       => null,
700
        'desc'        => null,
701
        'class'       => 'large-text',
702
        'disabled'    => false
703
    );
704
705
    $args = wp_parse_args( $args, $defaults );
706
707
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
708
    $disabled = '';
709
    if( $args['disabled'] ) {
710
        $disabled = ' disabled="disabled"';
711
    }
712
713
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
714
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['name'] ) . '">' . esc_html( $args['label'] ) . '</label>';
715
    $output .= '<textarea name="' . esc_attr( $args['name'] ) . '" id="' . wpinv_sanitize_key( $args['name'] ) . '" class="' . $class . '"' . $disabled . '>' . esc_attr( $args['value'] ) . '</textarea>';
716
717
    if ( ! empty( $args['desc'] ) ) {
718
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
719
    }
720
    $output .= '</span>';
721
722
    return $output;
723
}
724
725
function wpinv_html_ajax_user_search( $args = array() ) {
726
    $defaults = array(
727
        'name'        => 'user_id',
728
        'value'       => null,
729
        'placeholder' => __( 'Enter username', 'invoicing' ),
730
        'label'       => null,
731
        'desc'        => null,
732
        'class'       => '',
733
        'disabled'    => false,
734
        'autocomplete'=> 'off',
735
        'data'        => false
736
    );
737
738
    $args = wp_parse_args( $args, $defaults );
739
740
    $args['class'] = 'wpinv-ajax-user-search ' . $args['class'];
741
742
    $output  = '<span class="wpinv_user_search_wrap">';
743
        $output .= wpinv_html_text( $args );
744
        $output .= '<span class="wpinv_user_search_results hidden"><a class="wpinv-ajax-user-cancel" title="' . __( 'Cancel', 'invoicing' ) . '" aria-label="' . __( 'Cancel', 'invoicing' ) . '" href="#">x</a><span></span></span>';
745
    $output .= '</span>';
746
747
    return $output;
748
}
749
750
function wpinv_ip_geolocation() {
751
    global $wpinv_euvat;
752
    
753
    $ip         = !empty( $_GET['ip'] ) ? sanitize_text_field( $_GET['ip'] ) : '';    
754
    $content    = '';
755
    $iso        = '';
756
    $country    = '';
757
    $region     = '';
758
    $city       = '';
759
    $longitude  = '';
760
    $latitude   = '';
761
    $credit     = '';
762
    $address    = '';
763
    
764
    if ( wpinv_get_option( 'vat_ip_lookup' ) == 'geoip2' && $geoip2_city = $wpinv_euvat->geoip2_city_record( $ip ) ) {
765
        try {
766
            $iso        = $geoip2_city->country->isoCode;
767
            $country    = $geoip2_city->country->name;
768
            $region     = !empty( $geoip2_city->subdivisions ) && !empty( $geoip2_city->subdivisions[0]->name ) ? $geoip2_city->subdivisions[0]->name : '';
769
            $city       = $geoip2_city->city->name;
770
            $longitude  = $geoip2_city->location->longitude;
771
            $latitude   = $geoip2_city->location->latitude;
772
            $credit     = __( 'Geolocated using the information by MaxMind, available from <a href="http://www.maxmind.com" target="_blank">www.maxmind.com</a>', 'invoicing' );
773
        } catch( Exception $e ) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
774
    }
775
    
776
    if ( !( $iso && $longitude && $latitude ) && function_exists( 'simplexml_load_file' ) ) {
777
        try {
778
            $load_xml = simplexml_load_file( 'http://www.geoplugin.net/xml.gp?ip=' . $ip );
779
            
780
            if ( !empty( $load_xml ) && isset( $load_xml->geoplugin_countryCode ) && !empty( $load_xml->geoplugin_latitude ) && !empty( $load_xml->geoplugin_longitude ) ) {
781
                $iso        = $load_xml->geoplugin_countryCode;
782
                $country    = $load_xml->geoplugin_countryName;
783
                $region     = !empty( $load_xml->geoplugin_regionName ) ? $load_xml->geoplugin_regionName : '';
784
                $city       = !empty( $load_xml->geoplugin_city ) ? $load_xml->geoplugin_city : '';
785
                $longitude  = $load_xml->geoplugin_longitude;
786
                $latitude   = $load_xml->geoplugin_latitude;
787
                $credit     = $load_xml->geoplugin_credit;
0 ignored issues
show
Unused Code introduced by
The assignment to $credit is dead and can be removed.
Loading history...
788
                $credit     = __( 'Geolocated using the information by geoPlugin, available from <a href="http://www.geoplugin.com" target="_blank">www.geoplugin.com</a>', 'invoicing' ) . '<br>' . $load_xml->geoplugin_credit;
789
            }
790
        } catch( Exception $e ) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
791
    }
792
    
793
    if ( $iso && $longitude && $latitude ) {
794
        if ( $city ) {
795
            $address .= $city . ', ';
796
        }
797
        
798
        if ( $region ) {
799
            $address .= $region . ', ';
800
        }
801
        
802
        $address .= $country . ' (' . $iso . ')';
803
        $content = '<p>'. sprintf( __( '<b>Address:</b> %s', 'invoicing' ), $address ) . '</p>';
804
        $content .= '<p>'. $credit . '</p>';
805
    } else {
806
        $content = '<p>'. sprintf( __( 'Unable to find geolocation for the IP address: %s', 'invoicing' ), $ip ) . '</p>';
807
    }
808
    ?>
809
<!DOCTYPE html>
810
<html><head><title><?php echo sprintf( __( 'IP: %s', 'invoicing' ), $ip );?></title><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-rc.1/leaflet.css" /><style>html,body{height:100%;margin:0;padding:0;width:100%}body{text-align:center;background:#fff;color:#222;font-size:small;}body,p{font-family: arial,sans-serif}#map{margin:auto;width:100%;height:calc(100% - 120px);min-height:240px}</style></head>
811
<body>
812
    <?php if ( $latitude && $latitude ) { ?>
813
    <div id="map"></div>
814
        <script src="//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-rc.1/leaflet.js"></script>
815
        <script type="text/javascript">
816
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
817
            osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
818
            osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}),
819
            latlng = new L.LatLng(<?php echo $latitude;?>, <?php echo $longitude;?>);
820
821
        var map = new L.Map('map', {center: latlng, zoom: 12, layers: [osm]});
822
823
        var marker = new L.Marker(latlng);
824
        map.addLayer(marker);
825
826
        marker.bindPopup("<p><?php esc_attr_e( $address );?></p>");
827
    </script>
828
    <?php } ?>
829
    <div style="height:100px"><?php echo $content; ?></div>
830
</body></html>
831
<?php
832
    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
833
}
834
add_action( 'wp_ajax_wpinv_ip_geolocation', 'wpinv_ip_geolocation' );
835
add_action( 'wp_ajax_nopriv_wpinv_ip_geolocation', 'wpinv_ip_geolocation' );
836
837
// Set up the template for the invoice.
838
function wpinv_template( $template ) {
839
    global $post, $wp_query;
840
    
841
    if ( ( is_single() || is_404() ) && !empty( $post->ID ) && (get_post_type( $post->ID ) == 'wpi_invoice' or get_post_type( $post->ID ) == 'wpi_quote')) {
842
        if ( wpinv_user_can_view_invoice( $post->ID ) ) {
843
            $template = wpinv_get_template_part( 'wpinv-invoice-print', false, false );
844
        } else {
845
            $template = wpinv_get_template_part( 'wpinv-invalid-access', false, false );
846
        }
847
    }
848
849
    return $template;
850
}
851
852
function wpinv_get_business_address() {
853
    $business_address   = wpinv_store_address();
854
    $business_address   = !empty( $business_address ) ? wpautop( wp_kses_post( $business_address ) ) : '';
855
    
856
    /*
857
    $default_country    = wpinv_get_default_country();
858
    $default_state      = wpinv_get_default_state();
859
    
860
    $address_fields = array();
861
    if ( !empty( $default_state ) ) {
862
        $address_fields[] = wpinv_state_name( $default_state, $default_country );
863
    }
864
    
865
    if ( !empty( $default_country ) ) {
866
        $address_fields[] = wpinv_country_name( $default_country );
867
    }
868
    
869
    if ( !empty( $address_fields ) ) {
870
        $address_fields = implode( ", ", $address_fields );
871
                
872
        $business_address .= wpautop( wp_kses_post( $address_fields ) );
873
    }
874
    */
875
    
876
    $business_address = $business_address ? '<div class="address">' . $business_address . '</div>' : '';
877
    
878
    return apply_filters( 'wpinv_get_business_address', $business_address );
879
}
880
881
function wpinv_display_from_address() {
882
    global $wpinv_euvat;
883
    
884
    $from_name = $wpinv_euvat->get_company_name();
885
    if (empty($from_name)) {
886
        $from_name = wpinv_get_business_name();
887
    }
888
    ?><div class="from col-xs-2"><strong><?php _e( 'From:', 'invoicing' ) ?></strong></div>
889
    <div class="wrapper col-xs-10">
890
        <div class="name"><?php echo esc_html( $from_name ); ?></div>
891
        <?php if ( $address = wpinv_get_business_address() ) { ?>
892
        <div class="address"><?php echo wpautop( wp_kses_post( $address ) );?></div>
893
        <?php } ?>
894
        <?php if ( $email_from = wpinv_mail_get_from_address() ) { ?>
895
        <div class="email_from"><?php echo wp_sprintf( __( 'Email: %s', 'invoicing' ), $email_from );?></div>
896
        <?php } ?>
897
    </div>
898
    <?php
899
}
900
901
function wpinv_watermark( $id = 0 ) {
902
    $output = wpinv_get_watermark( $id );
903
    
904
    return apply_filters( 'wpinv_get_watermark', $output, $id );
905
}
906
907
function wpinv_get_watermark( $id ) {
908
    if ( !$id > 0 ) {
909
        return NULL;
910
    }
911
    $invoice = wpinv_get_invoice( $id );
912
    
913
    if ( !empty( $invoice ) && "wpi_invoice" === $invoice->post_type ) {
914
        if ( $invoice->is_paid() ) {
915
            return __( 'Paid', 'invoicing' );
916
        }
917
        if ( $invoice->is_refunded() ) {
918
            return __( 'Refunded', 'invoicing' );
919
        }
920
        if ( $invoice->has_status( array( 'wpi-cancelled' ) ) ) {
921
            return __( 'Cancelled', 'invoicing' );
922
        }
923
    }
924
    
925
    return NULL;
926
}
927
928
function wpinv_display_invoice_details( $invoice ) {
929
    global $wpinv_euvat;
930
    
931
    $invoice_id = $invoice->ID;
932
    $vat_name   = $wpinv_euvat->get_vat_name();
933
    $use_taxes  = wpinv_use_taxes();
934
    
935
    $invoice_status = wpinv_get_invoice_status( $invoice_id );
936
    ?>
937
    <table class="table table-bordered table-sm">
938
        <?php if ( $invoice_number = wpinv_get_invoice_number( $invoice_id ) ) { ?>
939
            <tr class="wpi-row-number">
940
                <th><?php echo apply_filters( 'wpinv_invoice_number_label', __( 'Invoice Number', 'invoicing' ), $invoice ); ?></th>
941
                <td><?php echo esc_html( $invoice_number ); ?></td>
942
            </tr>
943
        <?php } ?>
944
        <tr class="wpi-row-status">
945
            <th><?php echo apply_filters( 'wpinv_invoice_status_label', __( 'Invoice Status', 'invoicing' ), $invoice ); ?></th>
946
            <td><?php echo wpinv_invoice_status_label( $invoice_status, wpinv_get_invoice_status( $invoice_id, true ) ); ?></td>
947
        </tr>
948
        <?php if ( $invoice->is_renewal() ) { ?>
949
        <tr class="wpi-row-parent">
950
            <th><?php echo apply_filters( 'wpinv_invoice_parent_invoice_label', __( 'Parent Invoice', 'invoicing' ), $invoice ); ?></th>
951
            <td><?php echo wpinv_invoice_link( $invoice->parent_invoice ); ?></td>
952
        </tr>
953
        <?php } ?>
954
        <?php if ( ( $gateway_name = wpinv_get_payment_gateway_name( $invoice_id ) ) && ( $invoice->is_paid() || $invoice->is_refunded() ) ) { ?>
955
            <tr class="wpi-row-gateway">
956
                <th><?php echo apply_filters( 'wpinv_invoice_payment_method_label', __( 'Payment Method', 'invoicing' ), $invoice ); ?></th>
957
                <td><?php echo $gateway_name; ?></td>
958
            </tr>
959
        <?php } ?>
960
        <?php if ( $invoice_date = wpinv_get_invoice_date( $invoice_id ) ) { ?>
961
            <tr class="wpi-row-date">
962
                <th><?php echo apply_filters( 'wpinv_invoice_date_label', __( 'Invoice Date', 'invoicing' ), $invoice ); ?></th>
963
                <td><?php echo $invoice_date; ?></td>
964
            </tr>
965
        <?php } ?>
966
        <?php do_action( 'wpinv_display_details_before_due_date', $invoice_id ); ?>
967
        <?php if ( wpinv_get_option( 'overdue_active' ) && $invoice->needs_payment() && ( $due_date = $invoice->get_due_date( true ) ) ) { ?>
968
            <tr class="wpi-row-date">
969
                <th><?php echo apply_filters( 'wpinv_invoice_due_date_label', __( 'Due Date', 'invoicing' ), $invoice ); ?></th>
970
                <td><?php echo $due_date; ?></td>
971
            </tr>
972
        <?php } ?>
973
        <?php do_action( 'wpinv_display_details_after_due_date', $invoice_id ); ?>
974
        <?php if ( $owner_vat_number = $wpinv_euvat->get_vat_number() ) { ?>
975
            <tr class="wpi-row-ovatno">
976
                <th><?php echo apply_filters( 'wpinv_invoice_owner_vat_number_label', wp_sprintf( __( 'Owner %s Number', 'invoicing' ), $vat_name ), $invoice, $vat_name ); ?></th>
977
                <td><?php echo $owner_vat_number; ?></td>
978
            </tr>
979
        <?php } ?>
980
        <?php if ( $use_taxes && ( $user_vat_number = wpinv_get_invoice_vat_number( $invoice_id ) ) ) { ?>
981
            <tr class="wpi-row-uvatno">
982
                <th><?php echo apply_filters( 'wpinv_invoice_user_vat_number_label', wp_sprintf( __( 'Invoice %s Number', 'invoicing' ), $vat_name ), $invoice, $vat_name ); ?></th>
983
                <td><?php echo $user_vat_number; ?></td>
984
            </tr>
985
        <?php } ?>
986
        <tr class="table-active tr-total wpi-row-total">
987
            <th><strong><?php _e( 'Total Amount', 'invoicing' ) ?></strong></th>
988
            <td><strong><?php echo wpinv_payment_total( $invoice_id, true ); ?></strong></td>
989
        </tr>
990
    </table>
991
<?php
992
}
993
994
/**
995
 * Retrieves the address markup to use on Invoices.
996
 * 
997
 * @since 1.0.13
998
 * @see `wpinv_get_full_address_format`
999
 * @see `wpinv_get_invoice_address_replacements`
1000
 * @param array $billing_details customer's billing details
1001
 * @param  string $separator How to separate address lines.
1002
 * @return string
1003
 */
1004
function wpinv_get_invoice_address_markup( $billing_details, $separator = '<br/>' ) {
1005
1006
    // Retrieve the address markup...
1007
    $country= empty( $billing_details['country'] ) ? '' : $billing_details['country'];
1008
    $format = wpinv_get_full_address_format( $country );
1009
1010
    // ... and the replacements.
1011
    $replacements = wpinv_get_invoice_address_replacements( $billing_details );
1012
1013
    $formatted_address = str_ireplace( array_keys( $replacements ), $replacements, $format );
1014
    
1015
	// Remove unavailable tags.
1016
    $formatted_address = preg_replace( "/\{\{\w+\}\}/", '', $formatted_address );
1017
1018
    // Clean up white space.
1019
	$formatted_address = preg_replace( '/  +/', ' ', trim( $formatted_address ) );
1020
    $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
1021
    
1022
    // Break newlines apart and remove empty lines/trim commas and white space.
1023
	$formatted_address = array_filter( array_map( 'wpinv_trim_formatted_address_line', explode( "\n", $formatted_address ) ) );
1024
1025
    // Add html breaks.
1026
	$formatted_address = implode( $separator, $formatted_address );
1027
1028
	// We're done!
1029
	return $formatted_address;
1030
    
1031
}
1032
1033
function wpinv_display_to_address( $invoice_id = 0 ) {
1034
    $invoice = wpinv_get_invoice( $invoice_id );
1035
    
1036
    if ( empty( $invoice ) ) {
1037
        return NULL;
1038
    }
1039
    
1040
    $billing_details = $invoice->get_user_info();
1041
    $output = '<div class="to col-xs-2"><strong>' . __( 'To:', 'invoicing' ) . '</strong></div>';
1042
    $output .= '<div class="wrapper col-xs-10">';
1043
    
1044
    ob_start();
1045
    do_action( 'wpinv_display_to_address_top', $invoice );
1046
    $output .= ob_get_clean();
1047
    
1048
    $address_row = wpinv_get_invoice_address_markup( $billing_details );
1049
1050
    if ( $address_row ) {
1051
        $output .= '<div class="address">' . $address_row . '</div>';
1052
    }
1053
1054
    if ( $phone = $invoice->get_phone() ) {
1055
        $output .= '<div class="phone">' . wp_sprintf( __( 'Phone: %s', 'invoicing' ), esc_html( $phone ) ) . '</div>';
1056
    }
1057
    if ( $email = $invoice->get_email() ) {
1058
        $output .= '<div class="email">' . wp_sprintf( __( 'Email: %s' , 'invoicing'), esc_html( $email ) ) . '</div>';
1059
    }
1060
1061
    ob_start();
1062
    do_action( 'wpinv_display_to_address_bottom', $invoice );
1063
    $output .= ob_get_clean();
1064
    
1065
    $output .= '</div>';
1066
    $output = apply_filters( 'wpinv_display_to_address', $output, $invoice );
1067
1068
    echo $output;
1069
}
1070
1071
function wpinv_display_line_items( $invoice_id = 0 ) {
1072
    global $wpinv_euvat, $ajax_cart_details;
1073
    $invoice            = wpinv_get_invoice( $invoice_id );
1074
    $quantities_enabled = wpinv_item_quantities_enabled();
1075
    $use_taxes          = wpinv_use_taxes();
1076
    if ( !$use_taxes && (float)$invoice->get_tax() > 0 ) {
1077
        $use_taxes = true;
1078
    }
1079
    $zero_tax           = !(float)$invoice->get_tax() > 0 ? true : false;
1080
    $tax_label           = $use_taxes && $invoice->has_vat() ? $wpinv_euvat->get_vat_name() : __( 'Tax', 'invoicing' );
1081
    $tax_title          = !$zero_tax && $use_taxes ? ( wpinv_prices_include_tax() ? wp_sprintf( __( '(%s Incl.)', 'invoicing' ), $tax_label ) : wp_sprintf( __( '(%s Excl.)', 'invoicing' ), $tax_label ) ) : '';
1082
1083
    $cart_details       = $invoice->get_cart_details();
1084
    $ajax_cart_details  = $cart_details;
1085
    ob_start();
1086
    ?>
1087
    <table class="table table-sm table-bordered table-responsive">
1088
        <thead>
1089
            <tr>
1090
                <th class="name"><strong><?php _e( "Item Name", "invoicing" );?></strong></th>
1091
                <th class="rate"><strong><?php _e( "Price", "invoicing" );?></strong></th>
1092
                <?php if ($quantities_enabled) { ?>
1093
                    <th class="qty"><strong><?php _e( "Qty", "invoicing" );?></strong></th>
1094
                <?php } ?>
1095
                <?php if ($use_taxes && !$zero_tax) { ?>
1096
                    <th class="tax"><strong><?php echo $tax_label . ' <span class="normal small">(%)</span>'; ?></strong></th>
1097
                <?php } ?>
1098
                <th class="total"><strong><?php echo __( "Item Total", "invoicing" ) . ' <span class="normal small">' . $tax_title . '<span>';?></strong></th>
1099
            </tr>
1100
        </thead>
1101
        <tbody>
1102
        <?php 
1103
            if ( !empty( $cart_details ) ) {
1104
                do_action( 'wpinv_display_line_items_start', $invoice );
1105
1106
                $count = 0;
1107
                $cols  = 3;
1108
                foreach ( $cart_details as $key => $cart_item ) {
1109
                    $item_id    = !empty($cart_item['id']) ? absint( $cart_item['id'] ) : '';
1110
                    $item_price = isset($cart_item["item_price"]) ? wpinv_round_amount( $cart_item["item_price"] ) : 0;
1111
                    $line_total = isset($cart_item["subtotal"]) ? wpinv_round_amount( $cart_item["subtotal"] ) : 0;
1112
                    $quantity   = !empty($cart_item['quantity']) && (int)$cart_item['quantity'] > 0 ? absint( $cart_item['quantity'] ) : 1;
1113
1114
                    $item       = $item_id ? new WPInv_Item( $item_id ) : NULL;
1115
                    $summary    = '';
1116
	                $item_name    = '';
1117
                    $cols       = 3;
1118
                    if ( !empty($item) ) {
1119
                        $item_name  = $item->get_name();
1120
                        $summary    = $item->get_summary();
1121
                    }
1122
                    $item_name  = !empty($cart_item['name']) ? $cart_item['name'] : $item_name;
1123
1124
                    $summary = apply_filters( 'wpinv_print_invoice_line_item_summary', $summary, $cart_item, $item, $invoice );
1125
1126
                    $item_tax       = '';
1127
                    $tax_rate       = '';
1128
                    if ( $use_taxes && $cart_item['tax'] > 0 && $cart_item['subtotal'] > 0 ) {
1129
                        $item_tax = wpinv_price( wpinv_format_amount( $cart_item['tax'] ), $invoice->get_currency() );
1130
                        $tax_rate = !empty( $cart_item['vat_rate'] ) ? $cart_item['vat_rate'] : ( $cart_item['tax'] / $cart_item['subtotal'] ) * 100;
1131
                        $tax_rate = $tax_rate > 0 ? (float)wpinv_round_amount( $tax_rate, 4 ) : '';
1132
                        $tax_rate = $tax_rate != '' ? ' <small class="tax-rate">(' . $tax_rate . '%)</small>' : '';
1133
                    }
1134
1135
                    $line_item_tax = $item_tax . $tax_rate;
1136
1137
                    if ( $line_item_tax === '' ) {
1138
                        $line_item_tax = 0; // Zero tax
1139
                    }
1140
1141
                    $action = apply_filters( 'wpinv_display_line_item_action', '', $cart_item, $invoice, $cols );
1142
1143
                    $line_item = '<tr class="row-' . ( ($count % 2 == 0) ? 'even' : 'odd' ) . ' wpinv-item">';
1144
                        $line_item .= '<td class="name">' . $action. esc_html__( $item_name, 'invoicing' ) . wpinv_get_item_suffix( $item );
1145
                        if ( $summary !== '' ) {
1146
                            $line_item .= '<br/><small class="meta">' . wpautop( wp_kses_post( $summary ) ) . '</small>';
1147
                        }
1148
                        $line_item .= '</td>';
1149
1150
                        $line_item .= '<td class="rate">' . esc_html__( wpinv_price( wpinv_format_amount( $item_price ), $invoice->get_currency() ) ) . '</td>';
1151
                        if ($quantities_enabled) {
1152
                            $cols++;
1153
                            $line_item .= '<td class="qty">' . $quantity . '</td>';
1154
                        }
1155
                        if ($use_taxes && !$zero_tax) {
1156
                            $cols++;
1157
                            $line_item .= '<td class="tax">' . $line_item_tax . '</td>';
1158
                        }
1159
                        $line_item .= '<td class="total">' . esc_html__( wpinv_price( wpinv_format_amount( $line_total ), $invoice->get_currency() ) ) . '</td>';
1160
                    $line_item .= '</tr>';
1161
1162
                    echo apply_filters( 'wpinv_display_line_item', $line_item, $cart_item, $invoice, $cols );
1163
1164
                    $count++;
1165
                }
1166
1167
                do_action( 'wpinv_display_before_subtotal', $invoice, $cols );
1168
                ?>
1169
                <tr class="row-sub-total row_odd">
1170
                    <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_subtotal_label', '<strong>' . __( 'Sub Total', 'invoicing' ) . ':</strong>', $invoice ); ?></td>
1171
                    <td class="total"><strong><?php _e( wpinv_subtotal( $invoice_id, true ) ) ?></strong></td>
1172
                </tr>
1173
                <?php
1174
                do_action( 'wpinv_display_after_subtotal', $invoice, $cols );
1175
                
1176
                if ( wpinv_discount( $invoice_id, false ) > 0 ) {
1177
                    do_action( 'wpinv_display_before_discount', $invoice, $cols );
1178
                    ?>
1179
                        <tr class="row-discount">
1180
                            <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php wpinv_get_discount_label( wpinv_discount_code( $invoice_id ) ); ?>:</td>
1181
                            <td class="total"><?php echo wpinv_discount( $invoice_id, true, true ); ?></td>
1182
                        </tr>
1183
                    <?php
1184
                    do_action( 'wpinv_display_after_discount', $invoice, $cols );
1185
                }
1186
1187
                if ( $use_taxes ) {
1188
                    do_action( 'wpinv_display_before_tax', $invoice, $cols );
1189
                    ?>
1190
                    <tr class="row-tax">
1191
                        <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_tax_label', '<strong>' . $tax_label . ':</strong>', $invoice ); ?></td>
1192
                        <td class="total"><?php _e( wpinv_tax( $invoice_id, true ) ) ?></td>
1193
                    </tr>
1194
                    <?php
1195
                    do_action( 'wpinv_display_after_tax', $invoice, $cols );
1196
                }
1197
1198
                do_action( 'wpinv_display_before_total', $invoice, $cols );
1199
                ?>
1200
                <tr class="table-active row-total">
1201
                    <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_total_label', '<strong>' . __( 'Total', 'invoicing' ) . ':</strong>', $invoice ); ?></td>
1202
                    <td class="total"><strong><?php _e( wpinv_payment_total( $invoice_id, true ) ) ?></strong></td>
1203
                </tr>
1204
                <?php
1205
                do_action( 'wpinv_display_after_total', $invoice, $cols );
1206
1207
                do_action( 'wpinv_display_line_end', $invoice, $cols );
1208
            }
1209
        ?>
1210
        </tbody>
1211
    </table>
1212
    <?php
1213
    echo ob_get_clean();
1214
}
1215
1216
function wpinv_display_invoice_totals( $invoice_id = 0 ) {
1217
    $use_taxes = wpinv_use_taxes();
1218
1219
    do_action( 'wpinv_before_display_totals_table', $invoice_id ); 
1220
    ?>
1221
    <table class="table table-sm table-bordered table-responsive">
1222
        <tbody>
1223
            <?php do_action( 'wpinv_before_display_totals' ); ?>
1224
            <tr class="row-sub-total">
1225
                <td class="rate"><strong><?php _e( 'Sub Total', 'invoicing' ); ?></strong></td>
1226
                <td class="total"><strong><?php _e( wpinv_subtotal( $invoice_id, true ) ) ?></strong></td>
1227
            </tr>
1228
            <?php do_action( 'wpinv_after_display_totals' ); ?>
1229
            <?php if ( wpinv_discount( $invoice_id, false ) > 0 ) { ?>
1230
                <tr class="row-discount">
1231
                    <td class="rate"><?php wpinv_get_discount_label( wpinv_discount_code( $invoice_id ) ); ?></td>
1232
                    <td class="total"><?php echo wpinv_discount( $invoice_id, true, true ); ?></td>
1233
                </tr>
1234
            <?php do_action( 'wpinv_after_display_discount' ); ?>
1235
            <?php } ?>
1236
            <?php if ( $use_taxes ) { ?>
1237
            <tr class="row-tax">
1238
                <td class="rate"><?php _e( 'Tax', 'invoicing' ); ?></td>
1239
                <td class="total"><?php _e( wpinv_tax( $invoice_id, true ) ) ?></td>
1240
            </tr>
1241
            <?php do_action( 'wpinv_after_display_tax' ); ?>
1242
            <?php } ?>
1243
            <?php if ( $fees = wpinv_get_fees( $invoice_id ) ) { ?>
1244
                <?php foreach ( $fees as $fee ) { ?>
1245
                    <tr class="row-fee">
1246
                        <td class="rate"><?php echo $fee['label']; ?></td>
1247
                        <td class="total"><?php echo $fee['amount_display']; ?></td>
1248
                    </tr>
1249
                <?php } ?>
1250
            <?php } ?>
1251
            <tr class="table-active row-total">
1252
                <td class="rate"><strong><?php _e( 'Total', 'invoicing' ) ?></strong></td>
1253
                <td class="total"><strong><?php _e( wpinv_payment_total( $invoice_id, true ) ) ?></strong></td>
1254
            </tr>
1255
            <?php do_action( 'wpinv_after_totals' ); ?>
1256
        </tbody>
1257
1258
    </table>
1259
1260
    <?php do_action( 'wpinv_after_totals_table' );
1261
}
1262
1263
function wpinv_display_payments_info( $invoice_id = 0, $echo = true ) {
1264
    $invoice = wpinv_get_invoice( $invoice_id );
1265
1266
    ob_start();
1267
    do_action( 'wpinv_before_display_payments_info', $invoice_id );
1268
    if ( ( $gateway_title = $invoice->get_gateway_title() ) || $invoice->is_paid() || $invoice->is_refunded() ) {
1269
        ?>
1270
        <div class="wpi-payment-info">
1271
            <p class="wpi-payment-gateway"><?php echo wp_sprintf( __( 'Payment via %s', 'invoicing' ), $gateway_title ? $gateway_title : __( 'Manually', 'invoicing' ) ); ?></p>
1272
            <?php if ( $gateway_title ) { ?>
1273
            <p class="wpi-payment-transid"><?php echo wp_sprintf( __( 'Transaction ID: %s', 'invoicing' ), $invoice->get_transaction_id() ); ?></p>
1274
            <?php } ?>
1275
        </div>
1276
        <?php
1277
    }
1278
    do_action( 'wpinv_after_display_payments_info', $invoice_id );
1279
    $outout = ob_get_clean();
1280
1281
    if ( $echo ) {
1282
        echo $outout;
1283
    } else {
1284
        return $outout;
1285
    }
1286
}
1287
1288
function wpinv_display_style( $invoice ) {
1289
    wp_register_style( 'wpinv-single-style', WPINV_PLUGIN_URL . 'assets/css/invoice.css', array(), WPINV_VERSION );
1290
1291
    wp_print_styles( 'open-sans' );
1292
    wp_print_styles( 'wpinv-single-style' );
1293
1294
    $custom_css = wpinv_get_option('template_custom_css');
1295
    if(isset($custom_css) && !empty($custom_css)){
1296
        $custom_css     = wp_kses( $custom_css, array( '\'', '\"' ) );
0 ignored issues
show
Bug introduced by
array(''', '\"') of type array<integer,string> is incompatible with the type array<mixed,array>|string expected by parameter $allowed_html of wp_kses(). ( Ignorable by Annotation )

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

1296
        $custom_css     = wp_kses( $custom_css, /** @scrutinizer ignore-type */ array( '\'', '\"' ) );
Loading history...
1297
        $custom_css     = str_replace( '&gt;', '>', $custom_css );
1298
        echo '<style type="text/css">';
1299
        echo $custom_css;
1300
        echo '</style>';
1301
    }
1302
}
1303
add_action( 'wpinv_invoice_print_head', 'wpinv_display_style' );
1304
add_action( 'wpinv_invalid_invoice_head', 'wpinv_display_style' );
1305
1306
function wpinv_checkout_billing_details() {
1307
    $invoice_id = (int)wpinv_get_invoice_cart_id();
1308
    if (empty($invoice_id)) {
1309
        wpinv_error_log( 'Invoice id not found', 'ERROR', __FILE__, __LINE__ );
1310
        return null;
1311
    }
1312
1313
    $invoice = wpinv_get_invoice_cart( $invoice_id );
1314
    if (empty($invoice)) {
1315
        wpinv_error_log( 'Invoice not found', 'ERROR', __FILE__, __LINE__ );
1316
        return null;
1317
    }
1318
    $user_id        = $invoice->get_user_id();
1319
    $user_info      = $invoice->get_user_info();
1320
    $address_info   = wpinv_get_user_address( $user_id );
1321
1322
    if ( empty( $user_info['first_name'] ) && !empty( $user_info['first_name'] ) ) {
1323
        $user_info['first_name'] = $user_info['first_name'];
1324
        $user_info['last_name'] = $user_info['last_name'];
1325
    }
1326
1327
    if ( ( ( empty( $user_info['country'] ) && !empty( $address_info['country'] ) ) || ( empty( $user_info['state'] ) && !empty( $address_info['state'] ) && $user_info['country'] == $address_info['country'] ) ) ) {
1328
        $user_info['country']   = $address_info['country'];
1329
        $user_info['state']     = $address_info['state'];
1330
        $user_info['city']      = $address_info['city'];
1331
        $user_info['zip']       = $address_info['zip'];
1332
    }
1333
1334
    $address_fields = array(
1335
        'user_id',
1336
        'company',
1337
        'vat_number',
1338
        'email',
1339
        'phone',
1340
        'address'
1341
    );
1342
1343
    foreach ( $address_fields as $field ) {
1344
        if ( empty( $user_info[$field] ) ) {
1345
            $user_info[$field] = $address_info[$field];
1346
        }
1347
    }
1348
1349
    return apply_filters( 'wpinv_checkout_billing_details', $user_info, $invoice );
1350
}
1351
1352
function wpinv_admin_get_line_items($invoice = array()) {
1353
    $item_quantities    = wpinv_item_quantities_enabled();
1354
    $use_taxes          = wpinv_use_taxes();
1355
1356
    if ( empty( $invoice ) ) {
1357
        return NULL;
1358
    }
1359
1360
    $cart_items = $invoice->get_cart_details();
1361
    if ( empty( $cart_items ) ) {
1362
        return NULL;
1363
    }
1364
    ob_start();
1365
1366
    do_action( 'wpinv_admin_before_line_items', $cart_items, $invoice );
1367
1368
    $count = 0;
1369
    foreach ( $cart_items as $key => $cart_item ) {
1370
        $item_id    = $cart_item['id'];
1371
        $wpi_item   = $item_id > 0 ? new WPInv_Item( $item_id ) : NULL;
1372
1373
        if (empty($wpi_item)) {
1374
            continue;
1375
        }
1376
1377
        $item_price     = wpinv_price( wpinv_format_amount( $cart_item['item_price'] ), $invoice->get_currency() );
1378
        $quantity       = !empty( $cart_item['quantity'] ) && $cart_item['quantity'] > 0 ? $cart_item['quantity'] : 1;
1379
        $item_subtotal  = wpinv_price( wpinv_format_amount( $cart_item['subtotal'] ), $invoice->get_currency() );
1380
        $can_remove     = true;
1381
1382
        $summary = apply_filters( 'wpinv_admin_invoice_line_item_summary', '', $cart_item, $wpi_item, $invoice );
1383
1384
        $item_tax       = '';
1385
        $tax_rate       = '';
1386
        if ( $cart_item['tax'] > 0 && $cart_item['subtotal'] > 0 ) {
1387
            $item_tax = wpinv_price( wpinv_format_amount( $cart_item['tax'] ), $invoice->get_currency() );
1388
            $tax_rate = !empty( $cart_item['vat_rate'] ) ? $cart_item['vat_rate'] : ( $cart_item['tax'] / $cart_item['subtotal'] ) * 100;
1389
            $tax_rate = $tax_rate > 0 ? (float)wpinv_round_amount( $tax_rate, 4 ) : '';
1390
            $tax_rate = $tax_rate != '' ? ' <span class="tax-rate">(' . $tax_rate . '%)</span>' : '';
1391
        }
1392
        $line_item_tax = $item_tax . $tax_rate;
1393
1394
        if ( $line_item_tax === '' ) {
1395
            $line_item_tax = 0; // Zero tax
1396
        }
1397
1398
        $line_item = '<tr class="item item-' . ( ($count % 2 == 0) ? 'even' : 'odd' ) . '" data-item-id="' . $item_id . '">';
1399
            $line_item .= '<td class="id">' . $item_id . '</td>';
1400
            $line_item .= '<td class="title"><a href="' . get_edit_post_link( $item_id ) . '" target="_blank">' . $cart_item['name'] . '</a>' . wpinv_get_item_suffix( $wpi_item );
1401
            if ( $summary !== '' ) {
1402
                $line_item .= '<span class="meta">' . wpautop( wp_kses_post( $summary ) ) . '</span>';
1403
            }
1404
            $line_item .= '</td>';
1405
            $line_item .= '<td class="price">' . $item_price . '</td>';
1406
            
1407
            if ( $item_quantities ) {
1408
                if ( count( $cart_items ) == 1 && $quantity <= 1 ) {
1409
                    $can_remove = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $can_remove is dead and can be removed.
Loading history...
1410
                }
1411
                $line_item .= '<td class="qty" data-quantity="' . $quantity . '">&nbsp;&times;&nbsp;' . $quantity . '</td>';
1412
            } else {
1413
                if ( count( $cart_items ) == 1 ) {
1414
                    $can_remove = false;
1415
                }
1416
            }
1417
            $line_item .= '<td class="total">' . $item_subtotal . '</td>';
1418
            
1419
            if ( $use_taxes ) {
1420
                $line_item .= '<td class="tax">' . $line_item_tax . '</td>';
1421
            }
1422
            $line_item .= '<td class="action">';
1423
            if ( !$invoice->is_paid() && !$invoice->is_refunded() ) {
1424
                $line_item .= '<i class="fa fa-remove wpinv-item-remove"></i>';
1425
            }
1426
            $line_item .= '</td>';
1427
        $line_item .= '</tr>';
1428
1429
        echo apply_filters( 'wpinv_admin_line_item', $line_item, $cart_item, $invoice );
1430
1431
        $count++;
1432
    } 
1433
1434
    do_action( 'wpinv_admin_after_line_items', $cart_items, $invoice );
1435
1436
    return ob_get_clean();
1437
}
1438
1439
function wpinv_checkout_form() {
1440
    global $wpi_checkout_id;
1441
1442
    // Set current invoice id.
1443
    $wpi_checkout_id = wpinv_get_invoice_cart_id();
1444
1445
    //Maybe update the prices
1446
    if(! empty( $_GET['wpi_dynamic_item'] ) && ! empty( $_GET['wpi_dynamic_price'] ) ) {
1447
1448
        //If the invoice exists, update it with new pricing details
1449
        if (! empty( $wpi_checkout_id ) ) {
1450
1451
            $_invoice       = wpinv_get_invoice_cart();
1452
            $_cart_details  = $_invoice->get_cart_details();
1453
            $_dynamic_item  = sanitize_text_field( $_GET['wpi_dynamic_item'] );
1454
1455
            //First, fetch the item
1456
            $item    = new WPInv_Item( $_dynamic_item );
1457
    
1458
            //Next, ensure it supports dynamic pricing...
1459
            if( $item->supports_dynamic_pricing() && $item->get_is_dynamic_pricing() ) {
1460
                
1461
                //... and that the new price is not lower than the minimum price
1462
                $_dynamic_price = (float) wpinv_sanitize_amount( sanitize_text_field( $_GET['wpi_dynamic_price'] ) );
1463
                if( $_dynamic_price < $item->get_minimum_price() ) {
1464
                    $_dynamic_price = $item->get_minimum_price();
1465
                }
1466
1467
                //Finally, update our invoice with the new price
1468
                if ( !empty( $_cart_details ) ) {
1469
1470
                    foreach ( $_cart_details as $key => $item ) {
1471
                        if ( !empty( $item['id'] ) && $_dynamic_item == $item['id'] ) {
1472
                            $_cart_details[$key]['custom_price'] = $_dynamic_price;
1473
                            $_cart_details[$key]['item_price']   = $_dynamic_price;
1474
                        }
1475
                    }
1476
1477
                    $_meta = $_invoice->get_meta();
1478
                    $_meta['cart_details'] = $_cart_details;
1479
                    $_invoice->set( 'payment_meta', $_meta );
1480
                    $_invoice->set( 'cart_details', $_cart_details );
1481
                    $_invoice->recalculate_totals();
1482
1483
                }
1484
1485
            }
1486
            
1487
        }
1488
1489
    }
1490
1491
    $form_action  = esc_url( wpinv_get_checkout_uri() );
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_checkout_uri() can also be of type false; however, parameter $url of esc_url() 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

1491
    $form_action  = esc_url( /** @scrutinizer ignore-type */ wpinv_get_checkout_uri() );
Loading history...
1492
1493
    ob_start();
1494
	    do_action( 'wpinv_checkout_content_before' );
1495
        echo '<div id="wpinv_checkout_wrap">';
1496
1497
        if ( wpinv_get_cart_contents() || wpinv_cart_has_fees() ) {
1498
            ?>
1499
            <div id="wpinv_checkout_form_wrap" class="wpinv_clearfix table-responsive">
1500
                <?php do_action( 'wpinv_before_checkout_form' ); ?>
1501
                <form id="wpinv_checkout_form" class="wpi-form" action="<?php echo $form_action; ?>" method="POST">
1502
                    <?php
1503
                    do_action( 'wpinv_checkout_form_top' );
1504
                    do_action( 'wpinv_checkout_billing_info' );
1505
                    do_action( 'wpinv_checkout_cart' );
1506
                    do_action( 'wpinv_payment_mode_select'  );
1507
                    do_action( 'wpinv_checkout_form_bottom' )
1508
                    ?>
1509
                </form>
1510
                <?php do_action( 'wpinv_after_purchase_form' ); ?>
1511
            </div><!--end #wpinv_checkout_form_wrap-->
1512
        <?php
1513
        } else {
1514
            do_action( 'wpinv_cart_empty' );
1515
        }
1516
        echo '</div><!--end #wpinv_checkout_wrap-->';
1517
	    do_action( 'wpinv_checkout_content_after' );
1518
    return ob_get_clean();
1519
}
1520
1521
function wpinv_checkout_cart( $cart_details = array(), $echo = true ) {
1522
    global $ajax_cart_details;
1523
    $ajax_cart_details = $cart_details;
1524
1525
    ob_start();
1526
    do_action( 'wpinv_before_checkout_cart' );
1527
    echo '<div id="wpinv_checkout_cart_form" method="post">';
1528
        echo '<div id="wpinv_checkout_cart_wrap">';
1529
            wpinv_get_template_part( 'wpinv-checkout-cart' );
1530
        echo '</div>';
1531
    echo '</div>';
1532
    do_action( 'wpinv_after_checkout_cart' );
1533
    $content = ob_get_clean();
1534
1535
    if ( $echo ) {
1536
        echo $content;
1537
    } else {
1538
        return $content;
1539
    }
1540
}
1541
add_action( 'wpinv_checkout_cart', 'wpinv_checkout_cart', 10 );
1542
1543
function wpinv_empty_cart_message() {
1544
	return apply_filters( 'wpinv_empty_cart_message', '<span class="wpinv_empty_cart">' . __( 'Your cart is empty.', 'invoicing' ) . '</span>' );
1545
}
1546
1547
/**
1548
 * Echoes the Empty Cart Message
1549
 *
1550
 * @since 1.0
1551
 * @return void
1552
 */
1553
function wpinv_empty_checkout_cart() {
1554
	echo wpinv_empty_cart_message();
1555
}
1556
add_action( 'wpinv_cart_empty', 'wpinv_empty_checkout_cart' );
1557
1558
function wpinv_update_cart_button() {
1559
    if ( !wpinv_item_quantities_enabled() )
1560
        return;
1561
?>
1562
    <input type="submit" name="wpinv_update_cart_submit" class="wpinv-submit wpinv-no-js button" value="<?php _e( 'Update Cart', 'invoicing' ); ?>"/>
1563
    <input type="hidden" name="wpi_action" value="update_cart"/>
1564
<?php
1565
}
1566
1567
function wpinv_checkout_cart_columns() {
1568
    $default = 3;
1569
    if ( wpinv_item_quantities_enabled() ) {
1570
        $default++;
1571
    }
1572
    
1573
    if ( wpinv_use_taxes() ) {
1574
        $default++;
1575
    }
1576
1577
    return apply_filters( 'wpinv_checkout_cart_columns', $default );
1578
}
1579
1580
function wpinv_display_cart_messages() {
1581
    global $wpi_session;
1582
1583
    $messages = $wpi_session->get( 'wpinv_cart_messages' );
1584
1585
    if ( $messages ) {
1586
        foreach ( $messages as $message_id => $message ) {
1587
            // Try and detect what type of message this is
1588
            if ( strpos( strtolower( $message ), 'error' ) ) {
1589
                $type = 'error';
1590
            } elseif ( strpos( strtolower( $message ), 'success' ) ) {
1591
                $type = 'success';
1592
            } else {
1593
                $type = 'info';
1594
            }
1595
1596
            $classes = apply_filters( 'wpinv_' . $type . '_class', array( 'wpinv_errors', 'wpinv-alert', 'wpinv-alert-' . $type ) );
1597
1598
            echo '<div class="' . implode( ' ', $classes ) . '">';
1599
                // Loop message codes and display messages
1600
                    echo '<p class="wpinv_error" id="wpinv_msg_' . $message_id . '">' . $message . '</p>';
1601
            echo '</div>';
1602
        }
1603
1604
        // Remove all of the cart saving messages
1605
        $wpi_session->set( 'wpinv_cart_messages', null );
1606
    }
1607
}
1608
add_action( 'wpinv_before_checkout_cart', 'wpinv_display_cart_messages' );
1609
1610
function wpinv_discount_field() {
1611
    if ( isset( $_GET['wpi-gateway'] ) && wpinv_is_ajax_disabled() ) {
1612
        return; // Only show before a payment method has been selected if ajax is disabled
1613
    }
1614
1615
    if ( !wpinv_is_checkout() ) {
1616
        return;
1617
    }
1618
1619
    if ( wpinv_has_active_discounts() && wpinv_get_cart_total() ) {
1620
    ?>
1621
    <div id="wpinv-discount-field" class="panel panel-default">
1622
        <div class="panel-body">
1623
            <p>
1624
                <label class="wpinv-label" for="wpinv_discount_code"><strong><?php _e( 'Discount', 'invoicing' ); ?></strong></label>
1625
                <span class="wpinv-description"><?php _e( 'Enter a discount code if you have one.', 'invoicing' ); ?></span>
1626
            </p>
1627
            <div class="form-group row">
1628
                <div class="col-sm-4">
1629
                    <input class="wpinv-input form-control" type="text" id="wpinv_discount_code" name="wpinv_discount_code" placeholder="<?php _e( 'Enter discount code', 'invoicing' ); ?>"/>
1630
                </div>
1631
                <div class="col-sm-3">
1632
                    <button id="wpi-apply-discount" type="button" class="btn btn-success btn-sm"><?php _e( 'Apply Discount', 'invoicing' ); ?></button>
1633
                </div>
1634
                <div style="clear:both"></div>
1635
                <div class="col-sm-12 wpinv-discount-msg">
1636
                    <div class="alert alert-success"><i class="fa fa-check-circle"></i><span class="wpi-msg"></span></div>
1637
                    <div class="alert alert-error"><i class="fa fa-warning"></i><span class="wpi-msg"></span></div>
1638
                </div>
1639
            </div>
1640
        </div>
1641
    </div>
1642
<?php
1643
    }
1644
}
1645
add_action( 'wpinv_after_checkout_cart', 'wpinv_discount_field', -10 );
1646
1647
function wpinv_agree_to_terms_js() {
1648
    if ( wpinv_get_option( 'show_agree_to_terms', false ) ) {
1649
?>
1650
<script type="text/javascript">
1651
    jQuery(document).ready(function($){
1652
        $( document.body ).on('click', '.wpinv_terms_links', function(e) {
1653
            //e.preventDefault();
1654
            $('#wpinv_terms').slideToggle();
1655
            $('.wpinv_terms_links').toggle();
1656
            return false;
1657
        });
1658
    });
1659
</script>
1660
<?php
1661
    }
1662
}
1663
add_action( 'wpinv_checkout_form_top', 'wpinv_agree_to_terms_js' );
1664
1665
function wpinv_payment_mode_select() {
1666
    $gateways = wpinv_get_enabled_payment_gateways( true );
1667
    $gateways = apply_filters( 'wpinv_payment_gateways_on_cart', $gateways );
1668
    $invoice = wpinv_get_invoice( 0, true );
1669
1670
    do_action('wpinv_payment_mode_top');
1671
    $invoice_id = (int)$invoice->ID;
1672
    $chosen_gateway = wpinv_get_chosen_gateway( $invoice_id );
1673
    ?>
1674
    <div id="wpinv_payment_mode_select" data-gateway="<?php echo $chosen_gateway; ?>" <?php echo ( $invoice->is_free() ? 'style="display:none;" data-free="1"' : '' ); ?>>
1675
            <?php do_action( 'wpinv_payment_mode_before_gateways_wrap' ); ?>
1676
            <div id="wpinv-payment-mode-wrap" class="panel panel-default">
1677
                <div class="panel-heading"><h3 class="panel-title"><?php _e( 'Select Payment Method', 'invoicing' ); ?></h3></div>
1678
                <div class="panel-body list-group wpi-payment_methods">
1679
                    <?php
1680
                    do_action( 'wpinv_payment_mode_before_gateways' );
1681
1682
                    if ( !empty( $gateways ) ) {
1683
                        foreach ( $gateways as $gateway_id => $gateway ) {
1684
                            $checked       = checked( $gateway_id, $chosen_gateway, false );
1685
                            $button_label  = wpinv_get_gateway_button_label( $gateway_id );
1686
                            $gateway_label = wpinv_get_gateway_checkout_label( $gateway_id );
1687
                            $description   = wpinv_get_gateway_description( $gateway_id );
1688
                            ?>
1689
                            <div class="list-group-item">
1690
                                <div class="radio">
1691
                                    <label><input type="radio" data-button-text="<?php echo esc_attr( $button_label );?>" value="<?php echo esc_attr( $gateway_id ) ;?>" <?php echo $checked ;?> id="wpi_gateway_<?php echo esc_attr( $gateway_id );?>" name="wpi-gateway" class="wpi-pmethod"><?php echo esc_html( $gateway_label ); ?></label>
1692
                                </div>
1693
                                <div style="display:none;" class="payment_box wpi_gateway_<?php echo esc_attr( $gateway_id );?>" role="alert">
1694
                                    <?php if ( !empty( $description ) ) { ?>
1695
                                        <div class="wpi-gateway-desc alert alert-info"><?php _e( $description, 'invoicing' ); ?></div>
1696
                                    <?php } ?>
1697
                                    <?php do_action( 'wpinv_' . $gateway_id . '_cc_form', $invoice_id ) ;?>
1698
                                </div>
1699
                            </div>
1700
                            <?php
1701
                        }
1702
                    } else {
1703
                        echo '<div class="alert alert-warning">'. __( 'No payment gateway active', 'invoicing' ) .'</div>';
1704
                    }
1705
1706
                    do_action( 'wpinv_payment_mode_after_gateways' );
1707
                    ?>
1708
                </div>
1709
            </div>
1710
            <?php do_action( 'wpinv_payment_mode_after_gateways_wrap' ); ?>
1711
    </div>
1712
    <?php
1713
    do_action('wpinv_payment_mode_bottom');
1714
}
1715
add_action( 'wpinv_payment_mode_select', 'wpinv_payment_mode_select' );
1716
1717
/**
1718
 * Sanitizes a checkout field
1719
 */
1720
function wpinv_sanitize_checkout_field_args( $args ) {
1721
1722
    $name     = ( empty( $args['name'] ) ) ? 'wpinv_' . wp_generate_password( 12, false ) : $args['name'];
1723
    $id       = ( empty( $args['id'] ) ) ? $name : $args['id'];
1724
1725
    $defaults = array(
1726
        'id'                     => $id, // element id
1727
        'name'                   => $name, // input element name
1728
        'key'                    => ( ! isset( $args['key'] ) ) ? str_ireplace( 'wpinv_', '', $name ) : $args['key'], // value key in $billing_details
1729
        'input_class'            => 'wpi-input form-control', // input element class
1730
        'wrapper_class'          => 'wpi-cart-field wpi-col2', // p element class
1731
        'label_class'            => 'wpi-label', // label class
1732
        'placeholder'            => '', // First name.
1733
        'field_label'            => '',
1734
        'field_description'      => '',
1735
        'field_required'         => false,
1736
        'field_required_msg'     => sprintf(
1737
            __( '%s is required', 'invoicing' ),
1738
            ( empty( $args['field_label'] ) ) ? $name : $args['field_label']
1739
        ),
1740
        'field_type'             => 'text',
1741
        'show_in'                => array( 'email', 'checkout', 'details' ),
1742
    );
1743
1744
    return wp_parse_args( $args, $defaults );
1745
1746
}
1747
1748
/**
1749
 * Returns default checkout fields.
1750
 */
1751
function wpinv_get_default_checkout_fields() {
1752
    return array_map( 'wpinv_sanitize_checkout_field_args', wpinv_get_data( 'default-checkout-fields' ) );
0 ignored issues
show
Bug introduced by
It seems like wpinv_get_data('default-checkout-fields') can also be of type true; however, parameter $arr1 of array_map() does only seem to accept array, 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

1752
    return array_map( 'wpinv_sanitize_checkout_field_args', /** @scrutinizer ignore-type */ wpinv_get_data( 'default-checkout-fields' ) );
Loading history...
1753
}
1754
1755
/**
1756
 * Returns checkout fields.
1757
 */
1758
function wpinv_get_checkout_fields() {
1759
    $checkout_fields = wpinv_get_option( 'checkout_fields', null );
1760
1761
    if ( ! is_array( $checkout_fields ) ) {
1762
        $checkout_fields = wpinv_get_default_checkout_fields();
1763
    }
1764
1765
    $checkout_fields = apply_filters('wpinv_checkout_fields', $checkout_fields );
1766
1767
    return array_map( 'wpinv_sanitize_checkout_field_args', $checkout_fields );
1768
}
1769
1770
/**
1771
 * Returns an array of enabled checkout fields.
1772
 */
1773
function wpinv_prepare_checkout_fields( $billing_details = array() ) {
1774
1775
    if ( ! is_array( $billing_details ) ) {
1776
        $billing_details = array();
1777
    }
1778
1779
    if ( empty( $billing_details['country'] ) ) {
1780
        $billing_details['country'] = wpinv_default_billing_country();
1781
    }
1782
1783
    $fields       = wpinv_get_checkout_fields();
1784
    $field_types  = wpinv_get_data( 'field-types' );
1785
1786
    foreach ( $fields as $key => $field ) {
1787
1788
        // Is the field type registered?
1789
        if ( empty( $field['field_type'] ) || empty( $field_types[ $field['field_type'] ] ) ) {
1790
            unset( $fields[ $key ] );
1791
            continue;
1792
        }
1793
1794
        // Each field type has its own render callback.
1795
        $fields[ $key ]['render_cb'] = $field_types[ $field['field_type'] ]['render_cb'];
1796
1797
        // Add the current field value.
1798
        if ( isset( $field['key'] ) && isset( $billing_details[ $field['key'] ] ) ) {
1799
1800
            if ( 'select' == $field['field_type'] ) {
1801
                $fields[ $key ]['selected'] = $billing_details[ $field['key'] ];
1802
            } else {
1803
                $fields[ $key ]['value'] = $billing_details[ $field['key'] ];
1804
            }
1805
1806
        }
1807
1808
        $fields[ $key ]['billing_details'] = $billing_details;
1809
        $fields[ $key ]['class']           =  $field['input_class'];
1810
1811
    }
1812
1813
    return $fields;
1814
1815
}
1816
1817
function wpinv_checkout_billing_info() {
1818
    if ( wpinv_is_checkout() ) {
1819
1820
        // Prepare the billing details and checkout fields.
1821
        $billing_details = wpinv_checkout_billing_details();
1822
        $checkout_fields = wpinv_prepare_checkout_fields( $billing_details );
1823
1824
        ?>
1825
        <div id="wpinv-fields" class="clearfix">
1826
            <?php do_action( 'wpinv_before_billing_fields', $billing_details ); ?>
1827
            <div id="wpi-billing" class="wpi-billing clearfix panel panel-default">
1828
                <div class="panel-heading"><h3 class="panel-title"><?php _e( 'Billing Details', 'invoicing' );?></h3></div>
1829
                <div id="wpinv-fields-box" class="panel-body">
1830
1831
                    <?php 
1832
1833
                        do_action( 'wpinv_checkout_billing_fields_first', $billing_details );
1834
1835
                        $first_col = true;
1836
                        foreach ( $checkout_fields as $field_details ) {
1837
1838
                            $type = sanitize_html_class( $field_details['field_type'] );
1839
                            $name = sanitize_html_class( $field_details['name'] );
1840
1841
                            // Fire actions before a field is displayed.
1842
                            do_action( "wpinv_checkout_billing_fields_before_$name", $field_details, $billing_details );
1843
                            do_action( "wpinv_checkout_billing_fields_before_single_field", $name, $field_details, $billing_details );
1844
                            do_action( "wpinv_checkout_billing_fields_before_field_type_$type", $field_details, $billing_details );
1845
1846
                            // Display the opening wrapper.
1847
                            $wrapper_class  = esc_attr( $field_details['wrapper_class'] );
1848
                            $wrapper_class .=  empty( $first_col ) ? ' wpi-coll' : ' wpi-colf';
1849
                            $wrapper_id     = "wpinv_{$name}_box";
1850
                            echo "<p id='$wrapper_id' class='$wrapper_class'>";
1851
1852
                            // And (maybe) the label.
1853
                            $label = esc_html( $field_details['field_label'] );
1854
                            if ( ! empty( $label ) ) {
1855
1856
                                // Is this field required?
1857
                                if ( ! empty( $field_details['field_required'] ) ) {
1858
                                    $label .= '&nbsp;<span class="wpi-required">*</span>';
1859
                                }
1860
1861
                                $label_class = esc_attr( $field_details['label_class'] );
1862
                                $input_id    = esc_attr( $field_details['id'] );
1863
                                echo "<label for='$input_id' class='$label_class'>$label</label>";
1864
1865
                            }
1866
1867
                            // Finally, display the input.
1868
                            if ( function_exists( $field_details['render_cb'] ) ) {
1869
                                echo call_user_func( $field_details['render_cb'], $field_details );
1870
                            }
1871
1872
                            // Fire actions when displaying a field.
1873
                            do_action( "wpinv_checkout_billing_fields_$name", $field_details, $billing_details );
1874
                            do_action( "wpinv_checkout_billing_fields_single_field", $name, $field_details, $billing_details );
1875
                            do_action( "wpinv_checkout_billing_fields_field_type_$type", $field_details, $billing_details );
1876
1877
                            if ( ! empty( $field_details['field_description'] ) ) {
1878
                                echo "<div class='wpi-field-description'>{$field_details['field_description']}</div>";
1879
                            }
1880
1881
                            echo "</p>";
1882
1883
                            // Fire actions after a field is displayed.
1884
                            do_action( "wpinv_checkout_billing_fields_after_$name", $field_details, $billing_details );
1885
                            do_action( "wpinv_checkout_billing_fields_after_single_field", $name, $field_details, $billing_details );
1886
                            do_action( "wpinv_checkout_billing_fields_after_field_type_$type", $field_details, $billing_details );
1887
1888
                            $first_col = ! $first_col;
0 ignored issues
show
introduced by
The condition $first_col is always true.
Loading history...
1889
                        }
1890
1891
                        do_action( 'wpinv_checkout_billing_fields_last', $billing_details );
1892
1893
                    ?>
1894
1895
                    <div class="clearfix"></div>
1896
                </div>
1897
            </div>
1898
            <?php do_action( 'wpinv_after_billing_fields', $billing_details ); ?>
1899
        </div>
1900
        <?php
1901
    }
1902
}
1903
add_action( 'wpinv_checkout_billing_info', 'wpinv_checkout_billing_info' );
1904
1905
function wpinv_checkout_hidden_fields() {
1906
?>
1907
    <?php if ( is_user_logged_in() ) { ?>
1908
    <input type="hidden" name="wpinv_user_id" value="<?php echo get_current_user_id(); ?>"/>
1909
    <?php } ?>
1910
    <input type="hidden" name="wpi_action" value="payment" />
1911
<?php
1912
}
1913
1914
function wpinv_checkout_button_purchase() {
1915
    ob_start();
1916
?>
1917
    <input type="submit" class="btn btn-success wpinv-submit" id="wpinv-payment-button" data-value="<?php esc_attr_e( 'Proceed to Pay', 'invoicing' ) ?>" name="wpinv_payment" value="<?php esc_attr_e( 'Proceed to Pay', 'invoicing' ) ?>"/>
1918
<?php
1919
    return apply_filters( 'wpinv_checkout_button_purchase', ob_get_clean() );
1920
}
1921
1922
function wpinv_checkout_total() {
1923
    global $cart_total;
1924
?>
1925
<div id="wpinv_checkout_total" class="panel panel-info">
1926
    <div class="panel-body">
1927
    <?php
1928
    do_action( 'wpinv_purchase_form_before_checkout_total' );
1929
    ?>
1930
    <strong><?php _e( 'Invoice Total:', 'invoicing' ) ?></strong> <span class="wpinv-chdeckout-total"><?php echo $cart_total;?></span>
1931
    <?php
1932
    do_action( 'wpinv_purchase_form_after_checkout_total' );
1933
    ?>
1934
    </div>
1935
</div>
1936
<?php
1937
}
1938
add_action( 'wpinv_checkout_form_bottom', 'wpinv_checkout_total', 9998 );
1939
1940
function wpinv_checkout_accept_tandc() {
1941
    $page = wpinv_get_option( 'tandc_page' );
1942
    ?>
1943
    <div id="wpinv_checkout_tandc" class="panel panel-success">
1944
        <div class="panel-body">
1945
            <?php echo wpinv_get_policy_text(); ?>
1946
            <?php
1947
            if(isset($page) && (int)$page > 0 && apply_filters( 'wpinv_checkout_show_terms', true )){
1948
                $terms_link = esc_url( get_permalink( $page ) );
0 ignored issues
show
Bug introduced by
It seems like get_permalink($page) can also be of type false; however, parameter $url of esc_url() 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

1948
                $terms_link = esc_url( /** @scrutinizer ignore-type */ get_permalink( $page ) );
Loading history...
1949
                ?>
1950
                <label class="">
1951
                    <input type="checkbox" class="wpi-terms-checkbox" name="wpi_terms" id="wpi-terms" <?php checked( apply_filters( 'wpinv_terms_is_checked_default', isset( $_POST['wpi_terms'] ) ), true ); ?>> <span><?php printf( __( 'I&rsquo;ve read and accept the <a href="%s" target="_blank" class="wpi-terms-and-conditions-link">terms &amp; conditions</a>', 'invoicing' ), $terms_link ); ?></span> <span class="wpi-required">*</span>
1952
                </label>
1953
            <?php } ?>
1954
        </div>
1955
    </div>
1956
    <?php
1957
}
1958
add_action( 'wpinv_checkout_form_bottom', 'wpinv_checkout_accept_tandc', 9995 );
1959
1960
function wpinv_checkout_submit() {
1961
?>
1962
<div id="wpinv_purchase_submit" class="panel panel-success">
1963
    <div class="panel-body text-center">
1964
    <?php
1965
    do_action( 'wpinv_purchase_form_before_submit' );
1966
    wpinv_checkout_hidden_fields();
1967
    echo wpinv_checkout_button_purchase();
1968
    do_action( 'wpinv_purchase_form_after_submit' );
1969
    ?>
1970
    </div>
1971
</div>
1972
<?php
1973
}
1974
add_action( 'wpinv_checkout_form_bottom', 'wpinv_checkout_submit', 9999 );
1975
1976
function wpinv_receipt_billing_address( $invoice_id = 0 ) {
1977
    $invoice = wpinv_get_invoice( $invoice_id );
1978
1979
    if ( empty( $invoice ) ) {
1980
        return NULL;
1981
    }
1982
1983
    $billing_details = $invoice->get_user_info();
1984
    $address_row = wpinv_get_invoice_address_markup( $billing_details );
1985
1986
    ob_start();
1987
    ?>
1988
    <table class="table table-bordered table-sm wpi-billing-details">
1989
        <tbody>
1990
            <tr class="wpi-receipt-name">
1991
                <th class="text-left"><?php _e( 'Name', 'invoicing' ); ?></th>
1992
                <td><?php echo esc_html( trim( $billing_details['first_name'] . ' ' . $billing_details['last_name'] ) ) ;?></td>
1993
            </tr>
1994
            <tr class="wpi-receipt-email">
1995
                <th class="text-left"><?php _e( 'Email', 'invoicing' ); ?></th>
1996
                <td><?php echo $billing_details['email'] ;?></td>
1997
            </tr>
1998
            <tr class="wpi-receipt-address">
1999
                <th class="text-left"><?php _e( 'Address', 'invoicing' ); ?></th>
2000
                <td><?php echo $address_row ;?></td>
2001
            </tr>
2002
            <?php if ( $billing_details['phone'] ) { ?>
2003
            <tr class="wpi-receipt-phone">
2004
                <th class="text-left"><?php _e( 'Phone', 'invoicing' ); ?></th>
2005
                <td><?php echo esc_html( $billing_details['phone'] ) ;?></td>
2006
            </tr>
2007
            <?php } ?>
2008
        </tbody>
2009
    </table>
2010
    <?php
2011
    $output = ob_get_clean();
2012
    
2013
    $output = apply_filters( 'wpinv_receipt_billing_address', $output, $invoice_id );
2014
2015
    echo $output;
2016
}
2017
2018
function wpinv_filter_success_page_content( $content ) {
2019
    if ( isset( $_GET['payment-confirm'] ) && wpinv_is_success_page() ) {
2020
        if ( has_filter( 'wpinv_payment_confirm_' . sanitize_text_field( $_GET['payment-confirm'] ) ) ) {
2021
            $content = apply_filters( 'wpinv_payment_confirm_' . sanitize_text_field( $_GET['payment-confirm'] ), $content );
2022
        }
2023
    }
2024
2025
    return $content;
2026
}
2027
add_filter( 'the_content', 'wpinv_filter_success_page_content', 99999 );
2028
2029
function wpinv_receipt_actions( $invoice ) {
2030
    if ( !empty( $invoice ) ) {
2031
        $actions = array();
2032
2033
        if ( wpinv_user_can_view_invoice( $invoice->ID ) ) {
2034
            $actions['print']   = array(
2035
                'url'  => $invoice->get_view_url( true ),
2036
                'name' => __( 'Print Invoice', 'invoicing' ),
2037
                'class' => 'btn-primary',
2038
            );
2039
        }
2040
2041
        if ( is_user_logged_in() ) {
2042
            $actions['history'] = array(
2043
                'url'  => wpinv_get_history_page_uri(),
2044
                'name' => __( 'Invoice History', 'invoicing' ),
2045
                'class' => 'btn-warning',
2046
            );
2047
        }
2048
2049
        $actions = apply_filters( 'wpinv_invoice_receipt_actions', $actions, $invoice );
2050
2051
        if ( !empty( $actions ) ) {
2052
        ?>
2053
        <div class="wpinv-receipt-actions text-right">
2054
            <?php foreach ( $actions as $key => $action ) { $class = !empty($action['class']) ? sanitize_html_class( $action['class'] ) : ''; ?>
2055
            <a href="<?php echo esc_url( $action['url'] );?>" class="btn btn-sm <?php echo $class . ' ' . sanitize_html_class( $key );?>" <?php echo ( !empty($action['attrs']) ? $action['attrs'] : '' ) ;?>><?php echo esc_html( $action['name'] );?></a>
2056
            <?php } ?>
2057
        </div>
2058
        <?php
2059
        }
2060
    }
2061
}
2062
add_action( 'wpinv_receipt_start', 'wpinv_receipt_actions', -10, 1 );
2063
2064
function wpinv_invoice_link( $invoice_id ) {
2065
    $invoice = wpinv_get_invoice( $invoice_id );
2066
2067
    if ( empty( $invoice ) ) {
2068
        return NULL;
2069
    }
2070
2071
    $invoice_link = '<a href="' . esc_url( $invoice->get_view_url() ) . '">' . $invoice->get_number() . '</a>';
0 ignored issues
show
Bug introduced by
It seems like $invoice->get_view_url() can also be of type false; however, parameter $url of esc_url() 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

2071
    $invoice_link = '<a href="' . esc_url( /** @scrutinizer ignore-type */ $invoice->get_view_url() ) . '">' . $invoice->get_number() . '</a>';
Loading history...
2072
2073
    return apply_filters( 'wpinv_get_invoice_link', $invoice_link, $invoice );
2074
}
2075
2076
function wpinv_invoice_subscription_details( $invoice ) {
2077
    if ( !empty( $invoice ) && $invoice->is_recurring() && ! wpinv_is_subscription_payment( $invoice ) ) {
2078
        $subscription = wpinv_get_subscription( $invoice, true );
2079
2080
        if ( empty( $subscription ) ) {
2081
            return;
2082
        }
2083
2084
        $frequency = WPInv_Subscriptions::wpinv_get_pretty_subscription_frequency($subscription->period, $subscription->frequency);
2085
        $billing = wpinv_price(wpinv_format_amount($subscription->recurring_amount), wpinv_get_invoice_currency_code($subscription->parent_payment_id)) . ' / ' . $frequency;
2086
        $initial = wpinv_price(wpinv_format_amount($subscription->initial_amount), wpinv_get_invoice_currency_code($subscription->parent_payment_id));
2087
2088
        $payments = $subscription->get_child_payments();
2089
        ?>
2090
        <div class="wpinv-subscriptions-details">
2091
            <h3 class="wpinv-subscriptions-t"><?php echo apply_filters( 'wpinv_subscription_details_title', __( 'Subscription Details', 'invoicing' ) ); ?></h3>
2092
            <table class="table">
2093
                <thead>
2094
                    <tr>
2095
                        <th><?php _e( 'Billing Cycle', 'invoicing' ) ;?></th>
2096
                        <th><?php _e( 'Start Date', 'invoicing' ) ;?></th>
2097
                        <th><?php _e( 'Expiration Date', 'invoicing' ) ;?></th>
2098
                        <th class="text-center"><?php _e( 'Times Billed', 'invoicing' ) ;?></th>
2099
                        <th class="text-center"><?php _e( 'Status', 'invoicing' ) ;?></th>
2100
                    </tr>
2101
                </thead>
2102
                <tbody>
2103
                    <tr>
2104
                        <td><?php printf(_x('%s then %s', 'Initial subscription amount then billing cycle and amount', 'invoicing'), $initial, $billing); ?></td>
2105
                        <td><?php echo date_i18n(get_option('date_format'), strtotime($subscription->created, current_time('timestamp'))); ?></td>
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

2105
                        <td><?php echo date_i18n(/** @scrutinizer ignore-type */ get_option('date_format'), strtotime($subscription->created, current_time('timestamp'))); ?></td>
Loading history...
2106
                        <td><?php echo date_i18n(get_option('date_format'), strtotime($subscription->expiration, current_time('timestamp'))); ?></td>
2107
                        <td class="text-center"><?php echo $subscription->get_times_billed() . ' / ' . (($subscription->bill_times == 0) ? 'Until Cancelled' : $subscription->bill_times); ?></td>
2108
                        <td class="text-center wpi-sub-status"><?php echo $subscription->get_status_label(); ?></td>
2109
                    </tr>
2110
                </tbody>
2111
            </table>
2112
        </div>
2113
        <?php if ( !empty( $payments ) ) { ?>
2114
        <div class="wpinv-renewal-payments">
2115
            <h3 class="wpinv-renewals-t"><?php echo apply_filters( 'wpinv_renewal_payments_title', __( 'Renewal Payments', 'invoicing' ) ); ?></h3>
2116
            <table class="table">
2117
                <thead>
2118
                    <tr>
2119
                        <th>#</th>
2120
                        <th><?php _e( 'Invoice', 'invoicing' ) ;?></th>
2121
                        <th><?php _e( 'Date', 'invoicing' ) ;?></th>
2122
                        <th class="text-right"><?php _e( 'Amount', 'invoicing' ) ;?></th>
2123
                    </tr>
2124
                </thead>
2125
                <tbody>
2126
                    <?php
2127
                        $i = 1;
2128
                        foreach ( $payments as $payment ) {
2129
                            $invoice_id = $payment->ID;
2130
                    ?>
2131
                    <tr>
2132
                        <th scope="row"><?php echo $i;?></th>
2133
                        <td><?php echo wpinv_invoice_link( $invoice_id ) ;?></td>
2134
                        <td><?php echo wpinv_get_invoice_date( $invoice_id ); ?></td>
2135
                        <td class="text-right"><?php echo wpinv_payment_total( $invoice_id, true ); ?></td>
2136
                    </tr>
2137
                    <?php $i++; } ?>
2138
                </tbody>
2139
            </table>
2140
        </div>
2141
        <?php } ?>
2142
        <?php
2143
    }
2144
}
2145
2146
function wpinv_cart_total_label( $label, $invoice ) {
2147
    if ( empty( $invoice ) ) {
2148
        return $label;
2149
    }
2150
2151
    $prefix_label = '';
2152
    if ( $invoice->is_parent() && $item_id = $invoice->get_recurring() ) {
0 ignored issues
show
Unused Code introduced by
The assignment to $item_id is dead and can be removed.
Loading history...
2153
        $prefix_label   = '<span class="label label-primary label-recurring">' . __( 'Recurring Payment', 'invoicing' ) . '</span> ' . wpinv_subscription_payment_desc( $invoice );
2154
    } else if ( $invoice->is_renewal() ) {
2155
        $prefix_label   = '<span class="label label-primary label-renewal">' . __( 'Renewal Payment', 'invoicing' ) . '</span> ';        
2156
    }
2157
2158
    if ( $prefix_label != '' ) {
2159
        $label  = '<span class="wpinv-cart-sub-desc">' . $prefix_label . '</span> ' . $label;
2160
    }
2161
2162
    return $label;
2163
}
2164
add_filter( 'wpinv_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2165
add_filter( 'wpinv_email_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2166
add_filter( 'wpinv_print_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2167
2168
add_action( 'wpinv_invoice_print_middle', 'wpinv_invoice_subscription_details', 10, 1 );
2169
2170
function wpinv_invoice_print_description( $invoice ) {
2171
    if ( empty( $invoice ) ) {
2172
        return NULL;
2173
    }
2174
    if ( $description = wpinv_get_invoice_description( $invoice->ID ) ) {
2175
        ?>
2176
        <div class="row wpinv-lower">
2177
            <div class="col-sm-12 wpinv-description">
2178
                <?php echo wpautop( $description ); ?>
2179
            </div>
2180
        </div>
2181
        <?php
2182
    }
2183
}
2184
add_action( 'wpinv_invoice_print_middle', 'wpinv_invoice_print_description', 10.1, 1 );
0 ignored issues
show
Bug introduced by
10.1 of type double is incompatible with the type integer expected by parameter $priority of add_action(). ( Ignorable by Annotation )

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

2184
add_action( 'wpinv_invoice_print_middle', 'wpinv_invoice_print_description', /** @scrutinizer ignore-type */ 10.1, 1 );
Loading history...
2185
2186
function wpinv_invoice_print_payment_info( $invoice ) {
2187
    if ( empty( $invoice ) ) {
2188
        return NULL;
2189
    }
2190
2191
    if ( $payments_info = wpinv_display_payments_info( $invoice->ID, false ) ) {
2192
        ?>
2193
        <div class="row wpinv-payments">
2194
            <div class="col-sm-12">
2195
                <?php echo $payments_info; ?>
2196
            </div>
2197
        </div>
2198
        <?php 
2199
    }
2200
}
2201
// add_action( 'wpinv_invoice_print_after_line_items', 'wpinv_invoice_print_payment_info', 10, 1 );
2202
2203
function wpinv_get_invoice_note_line_item( $note, $echo = true ) {
2204
    if ( empty( $note ) ) {
2205
        return NULL;
2206
    }
2207
2208
    if ( is_int( $note ) ) {
2209
        $note = get_comment( $note );
2210
    }
2211
2212
    if ( !( is_object( $note ) && is_a( $note, 'WP_Comment' ) ) ) {
2213
        return NULL;
2214
    }
2215
2216
    $note_classes   = array( 'note' );
2217
    $note_classes[] = get_comment_meta( $note->comment_ID, '_wpi_customer_note', true ) ? 'customer-note' : '';
2218
    $note_classes[] = $note->comment_author === 'System' ? 'system-note' : '';
2219
    $note_classes   = apply_filters( 'wpinv_invoice_note_class', array_filter( $note_classes ), $note );
2220
    $note_classes   = !empty( $note_classes ) ? implode( ' ', $note_classes ) : '';
2221
2222
    ob_start();
2223
    ?>
2224
    <li rel="<?php echo absint( $note->comment_ID ) ; ?>" class="<?php echo esc_attr( $note_classes ); ?>">
2225
        <div class="note_content">
2226
            <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
2227
        </div>
2228
        <p class="meta">
2229
            <abbr class="exact-date" title="<?php echo $note->comment_date; ?>"><?php printf( __( '%1$s - %2$s at %3$s', 'invoicing' ), $note->comment_author, date_i18n( get_option( 'date_format' ), strtotime( $note->comment_date ) ), date_i18n( get_option( 'time_format' ), strtotime( $note->comment_date ) ) ); ?></abbr>&nbsp;&nbsp;
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

2229
            <abbr class="exact-date" title="<?php echo $note->comment_date; ?>"><?php printf( __( '%1$s - %2$s at %3$s', 'invoicing' ), $note->comment_author, date_i18n( /** @scrutinizer ignore-type */ get_option( 'date_format' ), strtotime( $note->comment_date ) ), date_i18n( get_option( 'time_format' ), strtotime( $note->comment_date ) ) ); ?></abbr>&nbsp;&nbsp;
Loading history...
2230
            <?php if ( $note->comment_author !== 'System' || wpinv_current_user_can_manage_invoicing() ) { ?>
2231
                <a href="#" class="delete_note"><?php _e( 'Delete note', 'invoicing' ); ?></a>
2232
            <?php } ?>
2233
        </p>
2234
    </li>
2235
    <?php
2236
    $note_content = ob_get_clean();
2237
    $note_content = apply_filters( 'wpinv_get_invoice_note_line_item', $note_content, $note, $echo );
2238
2239
    if ( $echo ) {
2240
        echo $note_content;
2241
    } else {
2242
        return $note_content;
2243
    }
2244
}
2245
2246
function wpinv_invalid_invoice_content() {
2247
    global $post;
2248
2249
    $invoice = wpinv_get_invoice( $post->ID );
2250
2251
    $error = __( 'This invoice is only viewable by clicking on the invoice link that was sent to you via email.', 'invoicing' );
2252
    if ( !empty( $invoice->ID ) && $invoice->has_status( array_keys( wpinv_get_invoice_statuses() ) ) ) {
2253
        if ( is_user_logged_in() ) {
2254
            if ( wpinv_require_login_to_checkout() ) {
2255
                if ( isset( $_GET['invoice_key'] ) && $_GET['invoice_key'] === $invoice->get_key() ) {
2256
                    $error = __( 'You are not allowed to view this invoice.', 'invoicing' );
2257
                }
2258
            }
2259
        } else {
2260
            if ( wpinv_require_login_to_checkout() ) {
2261
                if ( isset( $_GET['invoice_key'] ) && $_GET['invoice_key'] === $invoice->get_key() ) {
2262
                    $error = __( 'You must be logged in to view this invoice.', 'invoicing' );
2263
                }
2264
            }
2265
        }
2266
    } else {
2267
        $error = __( 'This invoice is deleted or does not exist.', 'invoicing' );
2268
    }
2269
    ?>
2270
    <div class="row wpinv-row-invalid">
2271
        <div class="col-md-6 col-md-offset-3 wpinv-message error">
2272
            <h3><?php _e( 'Access Denied', 'invoicing' ); ?></h3>
2273
            <p class="wpinv-msg-text"><?php echo $error; ?></p>
2274
        </div>
2275
    </div>
2276
    <?php
2277
}
2278
add_action( 'wpinv_invalid_invoice_content', 'wpinv_invalid_invoice_content' );
2279
2280
add_action( 'wpinv_checkout_billing_fields_last', 'wpinv_force_company_name_field');
2281
function wpinv_force_company_name_field(){
2282
    $invoice = wpinv_get_invoice_cart();
2283
    $user_id = wpinv_get_user_id( $invoice->ID );
2284
    $company = empty( $user_id ) ? "" : get_user_meta( $user_id, '_wpinv_company', true );
2285
    if ( 1 == wpinv_get_option( 'force_show_company' ) && !wpinv_use_taxes() ) {
2286
        ?>
2287
        <p class="wpi-cart-field wpi-col2 wpi-colf">
2288
            <label for="wpinv_company" class="wpi-label"><?php _e('Company Name', 'invoicing'); ?></label>
2289
            <?php
2290
            echo wpinv_html_text(array(
2291
                'id' => 'wpinv_company',
2292
                'name' => 'wpinv_company',
2293
                'value' => $company,
2294
                'class' => 'wpi-input form-control',
2295
                'placeholder' => __('Company name', 'invoicing'),
2296
            ));
2297
            ?>
2298
        </p>
2299
        <?php
2300
    }
2301
}
2302
2303
/**
2304
 * Function to get privacy policy text.
2305
 *
2306
 * @since 1.0.13
2307
 * @return string
2308
 */
2309
function wpinv_get_policy_text() {
2310
    $privacy_page_id = get_option( 'wp_page_for_privacy_policy', 0 );
2311
2312
    $text = wpinv_get_option('invoicing_privacy_checkout_message', sprintf( __( 'Your personal data will be used to process your invoice, payment and for other purposes described in our %s.', 'invoicing' ), '[wpinv_privacy_policy]' ));
2313
2314
    if(!$privacy_page_id){
2315
        $privacy_page_id = wpinv_get_option( 'privacy_page', 0 );
2316
    }
2317
2318
    $privacy_link    = $privacy_page_id ? '<a href="' . esc_url( get_permalink( $privacy_page_id ) ) . '" class="wpinv-privacy-policy-link" target="_blank">' . __( 'privacy policy', 'invoicing' ) . '</a>' : __( 'privacy policy', 'invoicing' );
0 ignored issues
show
Bug introduced by
It seems like get_permalink($privacy_page_id) can also be of type false; however, parameter $url of esc_url() 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

2318
    $privacy_link    = $privacy_page_id ? '<a href="' . esc_url( /** @scrutinizer ignore-type */ get_permalink( $privacy_page_id ) ) . '" class="wpinv-privacy-policy-link" target="_blank">' . __( 'privacy policy', 'invoicing' ) . '</a>' : __( 'privacy policy', 'invoicing' );
Loading history...
2319
2320
    $find_replace = array(
2321
        '[wpinv_privacy_policy]' => $privacy_link,
2322
    );
2323
2324
    $privacy_text = str_replace( array_keys( $find_replace ), array_values( $find_replace ), $text );
2325
2326
    return wp_kses_post(wpautop($privacy_text));
2327
}
2328
2329
2330
/**
2331
 * Allows the user to set their own price for an invoice item
2332
 */
2333
function wpinv_checkout_cart_item_name_your_price( $cart_item, $key ) {
2334
    
2335
    //Ensure we have an item id
2336
    if(! is_array( $cart_item ) || empty( $cart_item['id'] ) ) {
2337
        return;
2338
    }
2339
2340
    //Fetch the item
2341
    $item_id = $cart_item['id'];
2342
    $item    = new WPInv_Item( $item_id );
2343
    
2344
    if(! $item->supports_dynamic_pricing() || !$item->get_is_dynamic_pricing() ) {
2345
        return;
2346
    }
2347
2348
    //Fetch the dynamic pricing "strings"
2349
    $suggested_price_text = esc_html( wpinv_get_option( 'suggested_price_text', __( 'Suggested Price:', 'invoicing' ) ) );
2350
    $minimum_price_text   = esc_html( wpinv_get_option( 'minimum_price_text', __( 'Minimum Price:', 'invoicing' ) ) );
2351
    $name_your_price_text = esc_html( wpinv_get_option( 'name_your_price_text', __( 'Name Your Price', 'invoicing' ) ) );
2352
2353
    //Display a "name_your_price" button
2354
    echo " &mdash; <a href='#' class='wpinv-name-your-price-frontend small'>$name_your_price_text</a></div>";
2355
2356
    //Display a name_your_price form
2357
    echo '<div class="name-your-price-miniform">';
2358
    
2359
    //Maybe display the recommended price
2360
    if( $item->get_price() > 0 && !empty( $suggested_price_text ) ) {
2361
        $suggested_price = $item->get_the_price();
2362
        echo "<div>$suggested_price_text &mdash; $suggested_price</div>";
2363
    }
2364
2365
    //Display the update price form
2366
    $symbol         = wpinv_currency_symbol();
2367
    $position       = wpinv_currency_position();
2368
    $minimum        = esc_attr( $item->get_minimum_price() );
2369
    $price          = esc_attr( $cart_item['item_price'] );
2370
    $update         = esc_attr__( "Update", 'invoicing' );
2371
2372
    //Ensure it supports dynamic prici
2373
    if( $price < $minimum ) {
2374
        $price = $minimum;
2375
    }
2376
2377
    echo '<label>';
2378
    echo $position != 'right' ? $symbol . '&nbsp;' : '';
2379
    echo "<input type='number' min='$minimum' placeholder='$price' value='$price' class='wpi-field-price' />";
2380
    echo $position == 'right' ? '&nbsp;' . $symbol : '' ;
2381
    echo "</label>";
2382
    echo "<input type='hidden' value='$item_id' class='wpi-field-item' />";
2383
    echo "<a class='btn btn-success wpinv-submit wpinv-update-dynamic-price-frontend'>$update</a>";
2384
2385
    //Maybe display the minimum price
2386
    if( $item->get_minimum_price() > 0 && !empty( $minimum_price_text ) ) {
2387
        $minimum_price = wpinv_price( wpinv_format_amount( $item->get_minimum_price() ) );
2388
        echo "<div>$minimum_price_text &mdash; $minimum_price</div>";
2389
    }
2390
2391
    echo "</div>";
2392
2393
}
2394
add_action( 'wpinv_checkout_cart_item_price_after', 'wpinv_checkout_cart_item_name_your_price', 10, 2 );
2395
2396
function wpinv_oxygen_fix_conflict() {
2397
    global $ct_ignore_post_types;
2398
2399
    if ( ! is_array( $ct_ignore_post_types ) ) {
2400
        $ct_ignore_post_types = array();
2401
    }
2402
2403
    $post_types = array( 'wpi_discount', 'wpi_invoice', 'wpi_item' );
2404
2405
    foreach ( $post_types as $post_type ) {
2406
        $ct_ignore_post_types[] = $post_type;
2407
2408
        // Ignore post type
2409
        add_filter( 'pre_option_oxygen_vsb_ignore_post_type_' . $post_type, '__return_true', 999 );
2410
    }
2411
2412
    remove_filter( 'template_include', 'wpinv_template', 10, 1 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 1. ( Ignorable by Annotation )

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

2412
    /** @scrutinizer ignore-call */ 
2413
    remove_filter( 'template_include', 'wpinv_template', 10, 1 );

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...
2413
    add_filter( 'template_include', 'wpinv_template', 999, 1 );
2414
}