Passed
Pull Request — master (#377)
by Brian
11:41
created

wpinv_template()   A

Complexity

Conditions 6
Paths 3

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 7
c 1
b 0
f 1
dl 0
loc 17
rs 9.2222
cc 6
nc 3
nop 1
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 $_GET, and $_GET['vat_class'] is assigned to $vat_class in includes/admin/class-getpaid-post-types-admin.php on line 552
  1. Read from $_GET, and $_GET['vat_class'] is assigned to $vat_class
    in includes/admin/class-getpaid-post-types-admin.php on line 552
  2. wpinv_html_select() is called
    in includes/admin/class-getpaid-post-types-admin.php on line 556
  3. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 363
  2. Path: Read from $_GET, and $_GET['type'] is assigned to $type in includes/admin/class-getpaid-post-types-admin.php on line 577
  1. Read from $_GET, and $_GET['type'] is assigned to $type
    in includes/admin/class-getpaid-post-types-admin.php on line 577
  2. wpinv_html_select() is called
    in includes/admin/class-getpaid-post-types-admin.php on line 581
  3. Enters via parameter $args
    in includes/wpinv-template-functions.php on line 363
  3. Path: Read from $_GET, and $_GET['vat_rule'] is assigned to $vat_rule in includes/admin/class-getpaid-post-types-admin.php on line 522
  1. Read from $_GET, and $_GET['vat_rule'] is assigned to $vat_rule
    in includes/admin/class-getpaid-post-types-admin.php on line 522
  2. wpinv_html_select() is called
    in includes/admin/class-getpaid-post-types-admin.php on line 527
  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 4413
  3. wp_parse_str() is called
    in wordpress/wp-includes/functions.php on line 4419
  4. Enters via parameter $string
    in wordpress/wp-includes/formatting.php on line 4938
  5. parse_str() is called
    in wordpress/wp-includes/formatting.php on line 4939

General Strategies to prevent injection

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

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

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

$sanitized = (integer) $tainted;
Loading history...
382
383
    $data_elements = '';
384
    foreach ( $args['data'] as $key => $value ) {
385
        $data_elements .= ' data-' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
386
    }
387
388
    if( $args['multiple'] ) {
389
        $multiple = ' MULTIPLE';
390
    } else {
391
        $multiple = '';
392
    }
393
394
    if( $args['placeholder'] ) {
395
        $placeholder = $args['placeholder'];
396
    } else {
397
        $placeholder = '';
398
    }
399
    
400
    $options = '';
401
    if( !empty( $args['onchange'] ) ) {
402
        $options .= ' onchange="' . esc_attr( $args['onchange'] ) . '"';
403
    }
404
    
405
    if( !empty( $args['required'] ) ) {
406
        $options .= ' required="required"';
407
    }
408
    
409
    if( !empty( $args['disabled'] ) ) {
410
        $options .= ' disabled';
411
    }
412
    
413
    if( !empty( $args['readonly'] ) ) {
414
        $options .= ' readonly';
415
    }
416
417
    $class  = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
418
    $output = '<select name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" class="wpinv-select ' . $class . '"' . $multiple . ' data-placeholder="' . $placeholder . '" ' . trim( $options ) . $data_elements . '>';
419
420
    if ( $args['show_option_all'] ) {
421
        if( $args['multiple'] ) {
422
            $selected = selected( true, in_array( 0, $args['selected'] ), false );
423
        } else {
424
            $selected = selected( $args['selected'], 0, false );
425
        }
426
        $output .= '<option value="all"' . $selected . '>' . esc_html( $args['show_option_all'] ) . '</option>';
427
    }
428
429
    if ( !empty( $args['options'] ) ) {
430
431
        if ( $args['show_option_none'] ) {
432
            if( $args['multiple'] ) {
433
                $selected = selected( true, in_array( "", $args['selected'] ), false );
434
            } else {
435
                $selected = selected( $args['selected'] === "", true, false );
436
            }
437
            $output .= '<option value=""' . $selected . '>' . esc_html( $args['show_option_none'] ) . '</option>';
438
        }
439
440
        foreach( $args['options'] as $key => $option ) {
441
442
            if( $args['multiple'] && is_array( $args['selected'] ) ) {
443
                $selected = selected( true, (bool)in_array( $key, $args['selected'] ), false );
444
            } else {
445
                $selected = selected( $args['selected'], $key, false );
446
            }
447
448
            $output .= '<option value="' . esc_attr( $key ) . '"' . $selected . '>' . esc_html( $option ) . '</option>';
449
        }
450
    }
451
452
    $output .= '</select>';
453
454
    return $output;
455
}
456
457
function wpinv_item_dropdown( $args = array() ) {
458
    $defaults = array(
459
        'name'              => 'wpi_item',
460
        'id'                => 'wpi_item',
461
        'class'             => '',
462
        'multiple'          => false,
463
        'selected'          => 0,
464
        'number'            => 100,
465
        'placeholder'       => __( 'Choose a item', 'invoicing' ),
466
        'data'              => array( 'search-type' => 'item' ),
467
        'show_option_all'   => false,
468
        'show_option_none'  => false,
469
        'show_recurring'    => false,
470
    );
471
472
    $args = wp_parse_args( $args, $defaults );
473
474
    $item_args = array(
475
        'post_type'      => 'wpi_item',
476
        'orderby'        => 'title',
477
        'order'          => 'ASC',
478
        'posts_per_page' => $args['number']
479
    );
480
481
    $item_args  = apply_filters( 'wpinv_item_dropdown_query_args', $item_args, $args, $defaults );
482
483
    $items      = get_posts( $item_args );
484
    $options    = array();
485
    if ( $items ) {
486
        foreach ( $items as $item ) {
487
            $title = esc_html( $item->post_title );
488
            
489
            if ( !empty( $args['show_recurring'] ) ) {
490
                $title .= wpinv_get_item_suffix( $item->ID, false );
491
            }
492
            
493
            $options[ absint( $item->ID ) ] = $title;
494
        }
495
    }
496
497
    // This ensures that any selected items are included in the drop down
498
    if( is_array( $args['selected'] ) ) {
499
        foreach( $args['selected'] as $item ) {
500
            if( ! in_array( $item, $options ) ) {
501
                $title = get_the_title( $item );
502
                if ( !empty( $args['show_recurring'] ) ) {
503
                    $title .= wpinv_get_item_suffix( $item, false );
504
                }
505
                $options[$item] = $title;
506
            }
507
        }
508
    } elseif ( is_numeric( $args['selected'] ) && $args['selected'] !== 0 ) {
509
        if ( ! in_array( $args['selected'], $options ) ) {
510
            $title = get_the_title( $args['selected'] );
511
            if ( !empty( $args['show_recurring'] ) ) {
512
                $title .= wpinv_get_item_suffix( $args['selected'], false );
513
            }
514
            $options[$args['selected']] = get_the_title( $args['selected'] );
515
        }
516
    }
517
518
    $output = wpinv_html_select( array(
519
        'name'             => $args['name'],
520
        'selected'         => $args['selected'],
521
        'id'               => $args['id'],
522
        'class'            => $args['class'],
523
        'options'          => $options,
524
        'multiple'         => $args['multiple'],
525
        'placeholder'      => $args['placeholder'],
526
        'show_option_all'  => $args['show_option_all'],
527
        'show_option_none' => $args['show_option_none'],
528
        'data'             => $args['data'],
529
    ) );
530
531
    return $output;
532
}
533
534
/**
535
 * Returns an array of published items.
536
 */
537
function wpinv_get_published_items_for_dropdown() {
538
539
    $items = get_posts(
540
        array(
541
            'post_type'      => 'wpi_item',
542
            'orderby'        => 'title',
543
            'order'          => 'ASC',
544
            'posts_per_page' => '-1'
545
        )
546
    );
547
548
    $options = array();
549
    if ( $items ) {
550
        foreach ( $items as $item ) {
551
            $options[ $item->ID ] = esc_html( $item->post_title ) . wpinv_get_item_suffix( $item->ID, false );
552
        }
553
    }
554
555
    return $options;
556
}
557
558
function wpinv_html_checkbox( $args = array() ) {
559
    $defaults = array(
560
        'name'     => null,
561
        'current'  => null,
562
        'class'    => 'wpinv-checkbox',
563
        'options'  => array(
564
            'disabled' => false,
565
            'readonly' => false
566
        )
567
    );
568
569
    $args = wp_parse_args( $args, $defaults );
570
571
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
572
    $options = '';
573
    if ( ! empty( $args['options']['disabled'] ) ) {
574
        $options .= ' disabled="disabled"';
575
    } elseif ( ! empty( $args['options']['readonly'] ) ) {
576
        $options .= ' readonly';
577
    }
578
579
    $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 ) . ' />';
580
581
    return $output;
582
}
583
584
function wpinv_html_text( $args = array() ) {
585
    // Backwards compatibility
586
    if ( func_num_args() > 1 ) {
587
        $args = func_get_args();
588
589
        $name  = $args[0];
590
        $value = isset( $args[1] ) ? $args[1] : '';
591
        $label = isset( $args[2] ) ? $args[2] : '';
592
        $desc  = isset( $args[3] ) ? $args[3] : '';
593
    }
594
595
    $defaults = array(
596
        'id'           => '',
597
        'name'         => isset( $name )  ? $name  : 'text',
598
        'value'        => isset( $value ) ? $value : null,
599
        'label'        => isset( $label ) ? $label : null,
600
        'desc'         => isset( $desc )  ? $desc  : null,
601
        'placeholder'  => '',
602
        'class'        => 'regular-text',
603
        'disabled'     => false,
604
        'readonly'     => false,
605
        'required'     => false,
606
        'autocomplete' => '',
607
        'data'         => false
608
    );
609
610
    $args = wp_parse_args( $args, $defaults );
611
612
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
613
    $options = '';
614
    if( $args['required'] ) {
615
        $options .= ' required="required"';
616
    }
617
    if( $args['readonly'] ) {
618
        $options .= ' readonly';
619
    }
620
    if( $args['readonly'] ) {
621
        $options .= ' readonly';
622
    }
623
624
    $data = '';
625
    if ( !empty( $args['data'] ) ) {
626
        foreach ( $args['data'] as $key => $value ) {
627
            $data .= 'data-' . wpinv_sanitize_key( $key ) . '="' . esc_attr( $value ) . '" ';
628
        }
629
    }
630
631
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
632
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['id'] ) . '">' . esc_html( $args['label'] ) . '</label>';
633
    if ( ! empty( $args['desc'] ) ) {
634
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
635
    }
636
637
    $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 ) . '/>';
638
639
    $output .= '</span>';
640
641
    return $output;
642
}
643
644
function wpinv_html_date_field( $args = array() ) {
645
    if( empty( $args['class'] ) ) {
646
        $args['class'] = 'wpiDatepicker';
647
    } elseif( ! strpos( $args['class'], 'wpiDatepicker' ) ) {
648
        $args['class'] .= ' wpiDatepicker';
649
    }
650
651
    return wpinv_html_text( $args );
652
}
653
654
function wpinv_html_textarea( $args = array() ) {
655
    $defaults = array(
656
        'name'        => 'textarea',
657
        'value'       => null,
658
        'label'       => null,
659
        'desc'        => null,
660
        'class'       => 'large-text',
661
        'disabled'    => false,
662
        'placeholder' => '',
663
    );
664
665
    $args = wp_parse_args( $args, $defaults );
666
667
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
668
    $disabled = '';
669
    if( $args['disabled'] ) {
670
        $disabled = ' disabled="disabled"';
671
    }
672
673
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
674
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['name'] ) . '">' . esc_html( $args['label'] ) . '</label>';
675
    $output .= '<textarea name="' . esc_attr( $args['name'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" id="' . wpinv_sanitize_key( $args['name'] ) . '" class="' . $class . '"' . $disabled . '>' . esc_attr( $args['value'] ) . '</textarea>';
676
677
    if ( ! empty( $args['desc'] ) ) {
678
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
679
    }
680
    $output .= '</span>';
681
682
    return $output;
683
}
684
685
function wpinv_html_ajax_user_search( $args = array() ) {
686
    $defaults = array(
687
        'name'        => 'user_id',
688
        'value'       => null,
689
        'placeholder' => __( 'Enter username', 'invoicing' ),
690
        'label'       => null,
691
        'desc'        => null,
692
        'class'       => '',
693
        'disabled'    => false,
694
        'autocomplete'=> 'off',
695
        'data'        => false
696
    );
697
698
    $args = wp_parse_args( $args, $defaults );
699
700
    $args['class'] = 'wpinv-ajax-user-search ' . $args['class'];
701
702
    $output  = '<span class="wpinv_user_search_wrap">';
703
        $output .= wpinv_html_text( $args );
704
        $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>';
705
    $output .= '</span>';
706
707
    return $output;
708
}
709
710
function wpinv_ip_geolocation() {
711
    global $wpinv_euvat;
712
    
713
    $ip         = !empty( $_GET['ip'] ) ? sanitize_text_field( $_GET['ip'] ) : '';    
714
    $content    = '';
715
    $iso        = '';
716
    $country    = '';
717
    $region     = '';
718
    $city       = '';
719
    $longitude  = '';
720
    $latitude   = '';
721
    $credit     = '';
722
    $address    = '';
723
    
724
    if ( wpinv_get_option( 'vat_ip_lookup' ) == 'geoip2' && $geoip2_city = $wpinv_euvat->geoip2_city_record( $ip ) ) {
725
        try {
726
            $iso        = $geoip2_city->country->isoCode;
727
            $country    = $geoip2_city->country->name;
728
            $region     = !empty( $geoip2_city->subdivisions ) && !empty( $geoip2_city->subdivisions[0]->name ) ? $geoip2_city->subdivisions[0]->name : '';
729
            $city       = $geoip2_city->city->name;
730
            $longitude  = $geoip2_city->location->longitude;
731
            $latitude   = $geoip2_city->location->latitude;
732
            $credit     = __( 'Geolocated using the information by MaxMind, available from <a href="http://www.maxmind.com" target="_blank">www.maxmind.com</a>', 'invoicing' );
733
        } catch( Exception $e ) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
734
    }
735
    
736
    if ( !( $iso && $longitude && $latitude ) && function_exists( 'simplexml_load_file' ) ) {
737
        try {
738
            $load_xml = simplexml_load_file( 'http://www.geoplugin.net/xml.gp?ip=' . $ip );
739
            
740
            if ( !empty( $load_xml ) && isset( $load_xml->geoplugin_countryCode ) && !empty( $load_xml->geoplugin_latitude ) && !empty( $load_xml->geoplugin_longitude ) ) {
741
                $iso        = $load_xml->geoplugin_countryCode;
742
                $country    = $load_xml->geoplugin_countryName;
743
                $region     = !empty( $load_xml->geoplugin_regionName ) ? $load_xml->geoplugin_regionName : '';
744
                $city       = !empty( $load_xml->geoplugin_city ) ? $load_xml->geoplugin_city : '';
745
                $longitude  = $load_xml->geoplugin_longitude;
746
                $latitude   = $load_xml->geoplugin_latitude;
747
                $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...
748
                $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;
749
            }
750
        } catch( Exception $e ) { }
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
751
    }
752
    
753
    if ( $iso && $longitude && $latitude ) {
754
        if ( $city ) {
755
            $address .= $city . ', ';
756
        }
757
        
758
        if ( $region ) {
759
            $address .= $region . ', ';
760
        }
761
        
762
        $address .= $country . ' (' . $iso . ')';
763
        $content = '<p>'. sprintf( __( '<b>Address:</b> %s', 'invoicing' ), $address ) . '</p>';
764
        $content .= '<p>'. $credit . '</p>';
765
    } else {
766
        $content = '<p>'. sprintf( __( 'Unable to find geolocation for the IP address: %s', 'invoicing' ), $ip ) . '</p>';
767
    }
768
    ?>
769
<!DOCTYPE html>
770
<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>
771
<body>
772
    <?php if ( $latitude && $latitude ) { ?>
773
    <div id="map"></div>
774
        <script src="//cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-rc.1/leaflet.js"></script>
775
        <script type="text/javascript">
776
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
777
            osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
778
            osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}),
779
            latlng = new L.LatLng(<?php echo $latitude;?>, <?php echo $longitude;?>);
780
781
        var map = new L.Map('map', {center: latlng, zoom: 12, layers: [osm]});
782
783
        var marker = new L.Marker(latlng);
784
        map.addLayer(marker);
785
786
        marker.bindPopup("<p><?php esc_attr_e( $address );?></p>");
787
    </script>
788
    <?php } ?>
789
    <div style="height:100px"><?php echo $content; ?></div>
790
</body></html>
791
<?php
792
    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...
793
}
794
add_action( 'wp_ajax_wpinv_ip_geolocation', 'wpinv_ip_geolocation' );
795
add_action( 'wp_ajax_nopriv_wpinv_ip_geolocation', 'wpinv_ip_geolocation' );
796
797
// Set up the template for the invoice.
798
function wpinv_template( $template ) {
799
    global $post;
800
801
    if ( ( is_single() || is_404() ) && ! empty( $post->ID ) && getpaid_is_invoice_post_type( get_post_type( $post->ID ) ) ) {
802
803
        // If the user can view this invoice, display it.
804
        if ( wpinv_user_can_view_invoice( $post->ID ) ) {
805
            return wpinv_get_template_part( 'wpinv-invoice-print', false, false );
806
807
        // Else display an error message.
808
        } else {
809
            return wpinv_get_template_part( 'wpinv-invalid-access', false, false );
810
        }
811
812
    }
813
814
    return $template;
815
}
816
817
function wpinv_get_business_address() {
818
    $business_address   = wpinv_store_address();
819
    $business_address   = !empty( $business_address ) ? wpautop( wp_kses_post( $business_address ) ) : '';
820
    
821
    /*
822
    $default_country    = wpinv_get_default_country();
823
    $default_state      = wpinv_get_default_state();
824
    
825
    $address_fields = array();
826
    if ( !empty( $default_state ) ) {
827
        $address_fields[] = wpinv_state_name( $default_state, $default_country );
828
    }
829
    
830
    if ( !empty( $default_country ) ) {
831
        $address_fields[] = wpinv_country_name( $default_country );
832
    }
833
    
834
    if ( !empty( $address_fields ) ) {
835
        $address_fields = implode( ", ", $address_fields );
836
                
837
        $business_address .= wpautop( wp_kses_post( $address_fields ) );
838
    }
839
    */
840
    
841
    $business_address = $business_address ? '<div class="address">' . $business_address . '</div>' : '';
842
    
843
    return apply_filters( 'wpinv_get_business_address', $business_address );
844
}
845
846
function wpinv_display_from_address() {
847
    global $wpinv_euvat;
848
    
849
    $from_name = $wpinv_euvat->get_company_name();
850
    if (empty($from_name)) {
851
        $from_name = wpinv_get_business_name();
852
    }
853
    ?><div class="from col-xs-2"><strong><?php _e( 'From:', 'invoicing' ) ?></strong></div>
854
    <div class="wrapper col-xs-10">
855
        <div class="name"><?php echo esc_html( $from_name ); ?></div>
856
        <?php if ( $address = wpinv_get_business_address() ) { ?>
857
        <div class="address"><?php echo wpautop( wp_kses_post( $address ) );?></div>
858
        <?php } ?>
859
        <?php if ( $email_from = wpinv_mail_get_from_address() ) { ?>
860
        <div class="email_from"><?php echo wp_sprintf( __( 'Email: %s', 'invoicing' ), $email_from );?></div>
861
        <?php } ?>
862
    </div>
863
    <?php
864
}
865
866
function wpinv_watermark( $id = 0 ) {
867
    $output = wpinv_get_watermark( $id );
868
    
869
    return apply_filters( 'wpinv_get_watermark', $output, $id );
870
}
871
872
function wpinv_get_watermark( $id ) {
873
    if ( !$id > 0 ) {
874
        return NULL;
875
    }
876
    $invoice = wpinv_get_invoice( $id );
877
    
878
    if ( !empty( $invoice ) && "wpi_invoice" === $invoice->post_type ) {
0 ignored issues
show
Bug Best Practice introduced by
The property post_type does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
879
        if ( $invoice->is_paid() ) {
880
            return __( 'Paid', 'invoicing' );
881
        }
882
        if ( $invoice->is_refunded() ) {
883
            return __( 'Refunded', 'invoicing' );
884
        }
885
        if ( $invoice->has_status( array( 'wpi-cancelled' ) ) ) {
886
            return __( 'Cancelled', 'invoicing' );
887
        }
888
    }
889
    
890
    return NULL;
891
}
892
893
function wpinv_display_invoice_details( $invoice ) {
894
    global $wpinv_euvat;
895
    
896
    $invoice_id = $invoice->ID;
897
    $vat_name   = $wpinv_euvat->get_vat_name();
898
    $use_taxes  = wpinv_use_taxes();
899
    
900
    $invoice_status = wpinv_get_invoice_status( $invoice_id );
901
    ?>
902
    <table class="table table-bordered table-sm">
903
        <?php if ( $invoice_number = wpinv_get_invoice_number( $invoice_id ) ) { ?>
904
            <tr class="wpi-row-number">
905
                <th><?php echo apply_filters( 'wpinv_invoice_number_label', __( 'Invoice Number', 'invoicing' ), $invoice ); ?></th>
906
                <td><?php echo esc_html( $invoice_number ); ?></td>
907
            </tr>
908
        <?php } ?>
909
        <tr class="wpi-row-status">
910
            <th><?php echo apply_filters( 'wpinv_invoice_status_label', __( 'Invoice Status', 'invoicing' ), $invoice ); ?></th>
911
            <td><?php echo wpinv_invoice_status_label( $invoice_status, wpinv_get_invoice_status( $invoice_id, true ) ); ?></td>
912
        </tr>
913
        <?php if ( $invoice->is_renewal() ) { ?>
914
        <tr class="wpi-row-parent">
915
            <th><?php echo apply_filters( 'wpinv_invoice_parent_invoice_label', __( 'Parent Invoice', 'invoicing' ), $invoice ); ?></th>
916
            <td><?php echo wpinv_invoice_link( $invoice->parent_invoice ); ?></td>
917
        </tr>
918
        <?php } ?>
919
        <?php if ( ( $gateway_name = wpinv_get_payment_gateway_name( $invoice_id ) ) && ( $invoice->is_paid() || $invoice->is_refunded() ) ) { ?>
920
            <tr class="wpi-row-gateway">
921
                <th><?php echo apply_filters( 'wpinv_invoice_payment_method_label', __( 'Payment Method', 'invoicing' ), $invoice ); ?></th>
922
                <td><?php echo $gateway_name; ?></td>
923
            </tr>
924
        <?php } ?>
925
        <?php if ( $invoice_date = wpinv_get_invoice_date( $invoice_id ) ) { ?>
926
            <tr class="wpi-row-date">
927
                <th><?php echo apply_filters( 'wpinv_invoice_date_label', __( 'Invoice Date', 'invoicing' ), $invoice ); ?></th>
928
                <td><?php echo $invoice_date; ?></td>
929
            </tr>
930
        <?php } ?>
931
        <?php do_action( 'wpinv_display_details_before_due_date', $invoice_id ); ?>
932
        <?php if ( wpinv_get_option( 'overdue_active' ) && $invoice->needs_payment() && ( $due_date = $invoice->get_due_date( true ) ) ) { ?>
933
            <tr class="wpi-row-date">
934
                <th><?php echo apply_filters( 'wpinv_invoice_due_date_label', __( 'Due Date', 'invoicing' ), $invoice ); ?></th>
935
                <td><?php echo $due_date; ?></td>
936
            </tr>
937
        <?php } ?>
938
        <?php do_action( 'wpinv_display_details_after_due_date', $invoice_id ); ?>
939
        <?php if ( $owner_vat_number = $wpinv_euvat->get_vat_number() ) { ?>
940
            <tr class="wpi-row-ovatno">
941
                <th><?php echo apply_filters( 'wpinv_invoice_owner_vat_number_label', wp_sprintf( __( 'Owner %s Number', 'invoicing' ), $vat_name ), $invoice, $vat_name ); ?></th>
942
                <td><?php echo $owner_vat_number; ?></td>
943
            </tr>
944
        <?php } ?>
945
        <?php if ( $use_taxes && ( $user_vat_number = wpinv_get_invoice_vat_number( $invoice_id ) ) ) { ?>
946
            <tr class="wpi-row-uvatno">
947
                <th><?php echo apply_filters( 'wpinv_invoice_user_vat_number_label', wp_sprintf( __( 'Invoice %s Number', 'invoicing' ), $vat_name ), $invoice, $vat_name ); ?></th>
948
                <td><?php echo $user_vat_number; ?></td>
949
            </tr>
950
        <?php } ?>
951
        <tr class="table-active tr-total wpi-row-total">
952
            <th><strong><?php _e( 'Total Amount', 'invoicing' ) ?></strong></th>
953
            <td><strong><?php echo wpinv_payment_total( $invoice_id, true ); ?></strong></td>
954
        </tr>
955
        <?php if ( $subscription = wpinv_get_subscription( $invoice_id ) ) { ?>
956
        <tr class="table-active wpi-row-recurring-total">
957
            <th><?php echo apply_filters( 'wpinv_invoice_parent_invoice_label', __( 'Recurring Amount', 'invoicing' ), $invoice ); ?></th>
958
            <td><strong><?php echo wpinv_price( wpinv_format_amount( $subscription->recurring_amount ), $invoice->get_currency() ); ?></strong></td>
959
        </tr>
960
        <tr class="wpi-row-expires">
961
            <th><?php echo apply_filters( 'wpinv_invoice_parent_invoice_label', __( 'Renews On', 'invoicing' ), $invoice ); ?></th>
962
            <td><?php echo sanitize_text_field( $subscription->expiration ); ?></td>
963
        </tr>
964
        <?php } ?>
965
    </table>
966
<?php
967
}
968
969
/**
970
 * Retrieves the address markup to use on Invoices.
971
 * 
972
 * @since 1.0.13
973
 * @see `wpinv_get_full_address_format`
974
 * @see `wpinv_get_invoice_address_replacements`
975
 * @param array $billing_details customer's billing details
976
 * @param  string $separator How to separate address lines.
977
 * @return string
978
 */
979
function wpinv_get_invoice_address_markup( $billing_details, $separator = '<br/>' ) {
980
981
    // Retrieve the address markup...
982
    $country= empty( $billing_details['country'] ) ? '' : $billing_details['country'];
983
    $format = wpinv_get_full_address_format( $country );
984
985
    // ... and the replacements.
986
    $replacements = wpinv_get_invoice_address_replacements( $billing_details );
987
988
    $formatted_address = str_ireplace( array_keys( $replacements ), $replacements, $format );
989
    
990
	// Remove unavailable tags.
991
    $formatted_address = preg_replace( "/\{\{\w+\}\}/", '', $formatted_address );
992
993
    // Clean up white space.
994
	$formatted_address = preg_replace( '/  +/', ' ', trim( $formatted_address ) );
995
    $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
996
    
997
    // Break newlines apart and remove empty lines/trim commas and white space.
998
	$formatted_address = array_filter( array_map( 'wpinv_trim_formatted_address_line', explode( "\n", $formatted_address ) ) );
999
1000
    // Add html breaks.
1001
	$formatted_address = implode( $separator, $formatted_address );
1002
1003
	// We're done!
1004
	return $formatted_address;
1005
    
1006
}
1007
1008
function wpinv_display_to_address( $invoice_id = 0 ) {
1009
    $invoice = wpinv_get_invoice( $invoice_id );
1010
    
1011
    if ( empty( $invoice ) ) {
1012
        return NULL;
1013
    }
1014
    
1015
    $billing_details = $invoice->get_user_info();
1016
    $output = '<div class="to col-xs-2"><strong>' . __( 'To:', 'invoicing' ) . '</strong></div>';
1017
    $output .= '<div class="wrapper col-xs-10">';
1018
    
1019
    ob_start();
1020
    do_action( 'wpinv_display_to_address_top', $invoice );
1021
    $output .= ob_get_clean();
1022
    
1023
    $address_row = wpinv_get_invoice_address_markup( $billing_details );
1024
1025
    if ( $address_row ) {
1026
        $output .= '<div class="address">' . $address_row . '</div>';
1027
    }
1028
1029
    if ( $phone = $invoice->get_phone() ) {
1030
        $output .= '<div class="phone">' . wp_sprintf( __( 'Phone: %s', 'invoicing' ), esc_html( $phone ) ) . '</div>';
1031
    }
1032
    if ( $email = $invoice->get_email() ) {
1033
        $output .= '<div class="email">' . wp_sprintf( __( 'Email: %s' , 'invoicing'), esc_html( $email ) ) . '</div>';
1034
    }
1035
1036
    ob_start();
1037
    do_action( 'wpinv_display_to_address_bottom', $invoice );
1038
    $output .= ob_get_clean();
1039
    
1040
    $output .= '</div>';
1041
    $output = apply_filters( 'wpinv_display_to_address', $output, $invoice );
1042
1043
    echo $output;
1044
}
1045
1046
/**
1047
 * Displays invoice line items.
1048
 */
1049
function wpinv_display_line_items( $invoice_id = 0 ) {
1050
    global $wpinv_euvat, $ajax_cart_details;
1051
1052
    // Prepare the invoice.
1053
    $invoice = new WPInv_Invoice( $invoice_id );
1054
1055
    // Abort if there is no invoice.
1056
    if ( ! $invoice->get_id() ) {
1057
        return;
1058
    }
1059
1060
    $invoice            = wpinv_get_invoice( $invoice_id );
1061
    $quantities_enabled = wpinv_item_quantities_enabled();
1062
    $use_taxes          = wpinv_use_taxes();
1063
    if ( !$use_taxes && (float)$invoice->get_total_tax() > 0 ) {
1064
        $use_taxes = true;
1065
    }
1066
    $zero_tax           = !(float)$invoice->get_total_tax() > 0 ? true : false;
1067
    $tax_label           = $use_taxes && $invoice->has_vat() ? $wpinv_euvat->get_vat_name() : __( 'Tax', 'invoicing' );
0 ignored issues
show
Deprecated Code introduced by
The function WPInv_Invoice::has_vat() has been deprecated. ( Ignorable by Annotation )

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

1067
    $tax_label           = $use_taxes && /** @scrutinizer ignore-deprecated */ $invoice->has_vat() ? $wpinv_euvat->get_vat_name() : __( 'Tax', 'invoicing' );
Loading history...
1068
    $tax_title          = !$zero_tax && $use_taxes ? ( wpinv_prices_include_tax() ? wp_sprintf( __( '(%s Incl.)', 'invoicing' ), $tax_label ) : wp_sprintf( __( '(%s Excl.)', 'invoicing' ), $tax_label ) ) : '';
1069
1070
    $cart_details       = $invoice->get_cart_details();
1071
    $ajax_cart_details  = $cart_details;
1072
    ob_start();
1073
    ?>
1074
    <table class="table table-sm table-bordered">
1075
        <thead>
1076
            <tr>
1077
                <th class="name"><strong><?php _e( "Item Name", "invoicing" );?></strong></th>
1078
                <th class="rate"><strong><?php _e( "Price", "invoicing" );?></strong></th>
1079
                <?php if ($quantities_enabled) { ?>
1080
                    <th class="qty"><strong><?php _e( "Qty", "invoicing" );?></strong></th>
1081
                <?php } ?>
1082
                <?php if ($use_taxes && !$zero_tax) { ?>
1083
                    <th class="tax"><strong><?php echo $tax_label . ' <span class="normal small">(%)</span>'; ?></strong></th>
1084
                <?php } ?>
1085
                <th class="total"><strong><?php echo __( "Item Total", "invoicing" ) . ' <span class="normal small">' . $tax_title . '<span>';?></strong></th>
1086
            </tr>
1087
        </thead>
1088
        <tbody>
1089
        <?php 
1090
            if ( !empty( $cart_details ) ) {
1091
                do_action( 'wpinv_display_line_items_start', $invoice );
1092
1093
                $count = 0;
1094
                $cols  = 3;
1095
                foreach ( $cart_details as $key => $cart_item ) {
1096
                    $item_id    = !empty($cart_item['id']) ? absint( $cart_item['id'] ) : '';
1097
                    $item_price = isset($cart_item["item_price"]) ? wpinv_round_amount( $cart_item["item_price"] ) : 0;
1098
                    $line_total = isset($cart_item["subtotal"]) ? wpinv_round_amount( $cart_item["subtotal"] ) : 0;
1099
                    $quantity   = !empty($cart_item['quantity']) && (int)$cart_item['quantity'] > 0 ? absint( $cart_item['quantity'] ) : 1;
1100
1101
                    $item       = $item_id ? new WPInv_Item( $item_id ) : NULL;
1102
                    $summary    = '';
1103
	                $item_name    = '';
1104
                    $cols       = 3;
1105
                    if ( !empty($item) ) {
1106
                        $item_name  = $item->get_name();
1107
                        $summary    = $item->get_summary();
1108
                    }
1109
                    $item_name  = !empty($cart_item['name']) ? $cart_item['name'] : $item_name;
1110
1111
                    $summary = apply_filters( 'wpinv_print_invoice_line_item_summary', $summary, $cart_item, $item, $invoice );
1112
1113
                    $item_tax       = '';
1114
                    $tax_rate       = '';
1115
                    if ( $use_taxes && $cart_item['tax'] > 0 && $cart_item['subtotal'] > 0 ) {
1116
                        $item_tax = wpinv_price( wpinv_format_amount( $cart_item['tax'] ), $invoice->get_currency() );
1117
                        $tax_rate = !empty( $cart_item['vat_rate'] ) ? $cart_item['vat_rate'] : ( $cart_item['tax'] / $cart_item['subtotal'] ) * 100;
1118
                        $tax_rate = $tax_rate > 0 ? (float)wpinv_round_amount( $tax_rate, 4 ) : '';
1119
                        $tax_rate = $tax_rate != '' ? ' <small class="tax-rate">(' . $tax_rate . '%)</small>' : '';
1120
                    }
1121
1122
                    $line_item_tax = $item_tax . $tax_rate;
1123
1124
                    if ( $line_item_tax === '' ) {
1125
                        $line_item_tax = 0; // Zero tax
1126
                    }
1127
1128
                    $action = apply_filters( 'wpinv_display_line_item_action', '', $cart_item, $invoice, $cols );
1129
1130
                    $line_item = '<tr class="row-' . ( ($count % 2 == 0) ? 'even' : 'odd' ) . ' wpinv-item">';
1131
                        $line_item .= '<td class="name">' . $action. esc_html__( $item_name, 'invoicing' ) . wpinv_get_item_suffix( $item );
1132
                        if ( $summary !== '' ) {
1133
                            $line_item .= '<br/><small class="meta">' . wpautop( wp_kses_post( $summary ) ) . '</small>';
1134
                        }
1135
                        $line_item .= '</td>';
1136
1137
                        $line_item .= '<td class="rate">' . esc_html__( wpinv_price( wpinv_format_amount( $item_price ), $invoice->get_currency() ) ) . '</td>';
1138
                        if ($quantities_enabled) {
1139
                            $cols++;
1140
                            $line_item .= '<td class="qty">' . $quantity . '</td>';
1141
                        }
1142
                        if ($use_taxes && !$zero_tax) {
1143
                            $cols++;
1144
                            $line_item .= '<td class="tax">' . $line_item_tax . '</td>';
1145
                        }
1146
                        $line_item .= '<td class="total">' . esc_html__( wpinv_price( wpinv_format_amount( $line_total ), $invoice->get_currency() ) ) . '</td>';
1147
                    $line_item .= '</tr>';
1148
1149
                    echo apply_filters( 'wpinv_display_line_item', $line_item, $cart_item, $invoice, $cols );
1150
1151
                    $count++;
1152
                }
1153
1154
                do_action( 'wpinv_display_before_subtotal', $invoice, $cols );
1155
                ?>
1156
                <tr class="row-sub-total row_odd">
1157
                    <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_subtotal_label', '<strong>' . __( 'Sub Total', 'invoicing' ) . ':</strong>', $invoice ); ?></td>
1158
                    <td class="total"><strong><?php _e( wpinv_subtotal( $invoice_id, true ) ) ?></strong></td>
1159
                </tr>
1160
                <?php
1161
                do_action( 'wpinv_display_after_subtotal', $invoice, $cols );
1162
                
1163
                if ( wpinv_discount( $invoice_id, false ) > 0 ) {
1164
                    do_action( 'wpinv_display_before_discount', $invoice, $cols );
1165
                    ?>
1166
                        <tr class="row-discount">
1167
                            <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php wpinv_get_discount_label( wpinv_discount_code( $invoice_id ) ); ?>:</td>
1168
                            <td class="total"><?php echo wpinv_discount( $invoice_id, true, true ); ?></td>
1169
                        </tr>
1170
                    <?php
1171
                    do_action( 'wpinv_display_after_discount', $invoice, $cols );
1172
                }
1173
1174
                if ( $use_taxes ) {
1175
                    do_action( 'wpinv_display_before_tax', $invoice, $cols );
1176
                    ?>
1177
                    <tr class="row-tax">
1178
                        <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_tax_label', '<strong>' . $tax_label . ':</strong>', $invoice ); ?></td>
1179
                        <td class="total"><?php _e( wpinv_tax( $invoice_id, true ) ) ?></td>
1180
                    </tr>
1181
                    <?php
1182
                    do_action( 'wpinv_display_after_tax', $invoice, $cols );
1183
                }
1184
1185
                do_action( 'wpinv_display_before_total', $invoice, $cols );
1186
                ?>
1187
                <tr class="table-active row-total">
1188
                    <td class="rate" colspan="<?php echo ( $cols - 1 ); ?>"><?php echo apply_filters( 'wpinv_print_cart_total_label', '<strong>' . __( 'Total', 'invoicing' ) . ':</strong>', $invoice ); ?></td>
1189
                    <td class="total"><strong><?php _e( wpinv_payment_total( $invoice_id, true ) ) ?></strong></td>
1190
                </tr>
1191
                <?php
1192
                do_action( 'wpinv_display_after_total', $invoice, $cols );
1193
1194
                do_action( 'wpinv_display_line_end', $invoice, $cols );
1195
            }
1196
        ?>
1197
        </tbody>
1198
    </table>
1199
    <?php
1200
    echo ob_get_clean();
1201
}
1202
1203
/**
1204
 * @param WPInv_Invoice $invoice
1205
 */
1206
function wpinv_display_invoice_notes( $invoice ) {
1207
1208
    $notes = wpinv_get_invoice_notes( $invoice->ID, 'customer' );
1209
1210
    if ( empty( $notes ) ) {
1211
        return;
1212
    }
1213
1214
    echo '<div class="wpi_invoice_notes_container">';
1215
    echo '<h2>' . __( 'Invoice Notes', 'invoicing' ) .'</h2>';
1216
    echo '<ul class="wpi_invoice_notes">';
1217
1218
    foreach( $notes as $note ) {
1219
        wpinv_get_invoice_note_line_item( $note );
1220
    }
1221
1222
    echo '</ul>';
1223
    echo '</div>';
1224
}
1225
add_action( 'wpinv_invoice_print_after_line_items', 'wpinv_display_invoice_notes' );
1226
1227
function wpinv_display_invoice_totals( $invoice_id = 0 ) {
1228
    $use_taxes = wpinv_use_taxes();
1229
1230
    do_action( 'wpinv_before_display_totals_table', $invoice_id ); 
1231
    ?>
1232
    <table class="table table-sm table-bordered table-responsive">
1233
        <tbody>
1234
            <?php do_action( 'wpinv_before_display_totals' ); ?>
1235
            <tr class="row-sub-total">
1236
                <td class="rate"><strong><?php _e( 'Sub Total', 'invoicing' ); ?></strong></td>
1237
                <td class="total"><strong><?php _e( wpinv_subtotal( $invoice_id, true ) ) ?></strong></td>
1238
            </tr>
1239
            <?php do_action( 'wpinv_after_display_totals' ); ?>
1240
            <?php if ( wpinv_discount( $invoice_id, false ) > 0 ) { ?>
1241
                <tr class="row-discount">
1242
                    <td class="rate"><?php wpinv_get_discount_label( wpinv_discount_code( $invoice_id ) ); ?></td>
1243
                    <td class="total"><?php echo wpinv_discount( $invoice_id, true, true ); ?></td>
1244
                </tr>
1245
            <?php do_action( 'wpinv_after_display_discount' ); ?>
1246
            <?php } ?>
1247
            <?php if ( $use_taxes ) { ?>
1248
            <tr class="row-tax">
1249
                <td class="rate"><?php _e( 'Tax', 'invoicing' ); ?></td>
1250
                <td class="total"><?php _e( wpinv_tax( $invoice_id, true ) ) ?></td>
1251
            </tr>
1252
            <?php do_action( 'wpinv_after_display_tax' ); ?>
1253
            <?php } ?>
1254
            <?php if ( $fees = wpinv_get_fees( $invoice_id ) ) { ?>
1255
                <?php foreach ( $fees as $fee ) { ?>
1256
                    <tr class="row-fee">
1257
                        <td class="rate"><?php echo $fee['label']; ?></td>
1258
                        <td class="total"><?php echo $fee['amount_display']; ?></td>
1259
                    </tr>
1260
                <?php } ?>
1261
            <?php } ?>
1262
            <tr class="table-active row-total">
1263
                <td class="rate"><strong><?php _e( 'Total', 'invoicing' ) ?></strong></td>
1264
                <td class="total"><strong><?php _e( wpinv_payment_total( $invoice_id, true ) ) ?></strong></td>
1265
            </tr>
1266
            <?php do_action( 'wpinv_after_totals' ); ?>
1267
        </tbody>
1268
1269
    </table>
1270
1271
    <?php do_action( 'wpinv_after_totals_table' );
1272
}
1273
1274
function wpinv_display_payments_info( $invoice_id = 0, $echo = true ) {
1275
    $invoice = wpinv_get_invoice( $invoice_id );
1276
1277
    ob_start();
1278
    do_action( 'wpinv_before_display_payments_info', $invoice_id );
1279
    if ( ( $gateway_title = $invoice->get_gateway_title() ) || $invoice->is_paid() || $invoice->is_refunded() ) {
1280
        ?>
1281
        <div class="wpi-payment-info">
1282
            <p class="wpi-payment-gateway"><?php echo wp_sprintf( __( 'Payment via %s', 'invoicing' ), $gateway_title ? $gateway_title : __( 'Manually', 'invoicing' ) ); ?></p>
1283
            <?php if ( $gateway_title ) { ?>
1284
            <p class="wpi-payment-transid"><?php echo wp_sprintf( __( 'Transaction ID: %s', 'invoicing' ), $invoice->get_transaction_id() ); ?></p>
1285
            <?php } ?>
1286
        </div>
1287
        <?php
1288
    }
1289
    do_action( 'wpinv_after_display_payments_info', $invoice_id );
1290
    $outout = ob_get_clean();
1291
1292
    if ( $echo ) {
1293
        echo $outout;
1294
    } else {
1295
        return $outout;
1296
    }
1297
}
1298
1299
function wpinv_display_style( $invoice ) {
1300
    wp_register_style( 'wpinv-single-style', WPINV_PLUGIN_URL . 'assets/css/invoice.css', array(), WPINV_VERSION );
1301
1302
    wp_print_styles( 'open-sans' );
1303
    wp_print_styles( 'wpinv-single-style' );
1304
1305
    $custom_css = wpinv_get_option('template_custom_css');
1306
    if(isset($custom_css) && !empty($custom_css)){
1307
        $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

1307
        $custom_css     = wp_kses( $custom_css, /** @scrutinizer ignore-type */ array( '\'', '\"' ) );
Loading history...
1308
        $custom_css     = str_replace( '&gt;', '>', $custom_css );
1309
        echo '<style type="text/css">';
1310
        echo $custom_css;
1311
        echo '</style>';
1312
    }
1313
}
1314
add_action( 'wpinv_invoice_print_head', 'wpinv_display_style' );
1315
add_action( 'wpinv_invalid_invoice_head', 'wpinv_display_style' );
1316
1317
function wpinv_checkout_billing_details() {
1318
    $invoice_id = (int)wpinv_get_invoice_cart_id();
1319
    if (empty($invoice_id)) {
1320
        wpinv_error_log( 'Invoice id not found', 'ERROR', __FILE__, __LINE__ );
1321
        return null;
1322
    }
1323
1324
    $invoice = wpinv_get_invoice_cart( $invoice_id );
1325
    if (empty($invoice)) {
1326
        wpinv_error_log( 'Invoice not found', 'ERROR', __FILE__, __LINE__ );
1327
        return null;
1328
    }
1329
    $user_id        = $invoice->get_user_id();
1330
    $user_info      = $invoice->get_user_info();
1331
    $address_info   = wpinv_get_user_address( $user_id );
1332
1333
    if ( empty( $user_info['first_name'] ) && !empty( $user_info['first_name'] ) ) {
1334
        $user_info['first_name'] = $user_info['first_name'];
1335
        $user_info['last_name'] = $user_info['last_name'];
1336
    }
1337
1338
    if ( ( ( empty( $user_info['country'] ) && !empty( $address_info['country'] ) ) || ( empty( $user_info['state'] ) && !empty( $address_info['state'] ) && $user_info['country'] == $address_info['country'] ) ) ) {
1339
        $user_info['country']   = $address_info['country'];
1340
        $user_info['state']     = $address_info['state'];
1341
        $user_info['city']      = $address_info['city'];
1342
        $user_info['zip']       = $address_info['zip'];
1343
    }
1344
1345
    $address_fields = array(
1346
        'user_id',
1347
        'company',
1348
        'vat_number',
1349
        'email',
1350
        'phone',
1351
        'address'
1352
    );
1353
1354
    foreach ( $address_fields as $field ) {
1355
        if ( empty( $user_info[$field] ) ) {
1356
            $user_info[$field] = $address_info[$field];
1357
        }
1358
    }
1359
1360
    return apply_filters( 'wpinv_checkout_billing_details', $user_info, $invoice );
1361
}
1362
1363
function wpinv_admin_get_line_items($invoice = array()) {
1364
    $item_quantities    = wpinv_item_quantities_enabled();
1365
    $use_taxes          = wpinv_use_taxes();
1366
1367
    if ( empty( $invoice ) ) {
1368
        return NULL;
1369
    }
1370
1371
    $cart_items = $invoice->get_cart_details();
1372
    if ( empty( $cart_items ) ) {
1373
        return NULL;
1374
    }
1375
1376
    ob_start();
1377
1378
    do_action( 'wpinv_admin_before_line_items', $cart_items, $invoice );
1379
1380
    $count = 0;
1381
    foreach ( $cart_items as $key => $cart_item ) {
1382
        $item_id    = $cart_item['id'];
1383
        $wpi_item   = $item_id > 0 ? new WPInv_Item( $item_id ) : NULL;
1384
1385
        if (empty($wpi_item)) {
1386
            continue;
1387
        }
1388
1389
        $item_price     = wpinv_price( wpinv_format_amount( $cart_item['item_price'] ), $invoice->get_currency() );
1390
        $quantity       = !empty( $cart_item['quantity'] ) && $cart_item['quantity'] > 0 ? $cart_item['quantity'] : 1;
1391
        $item_subtotal  = wpinv_price( wpinv_format_amount( $cart_item['subtotal'] ), $invoice->get_currency() );
1392
        $can_remove     = true;
1393
1394
        $summary = apply_filters( 'wpinv_admin_invoice_line_item_summary', '', $cart_item, $wpi_item, $invoice );
1395
1396
        $item_tax       = '';
1397
        $tax_rate       = '';
1398
        if ( $invoice->is_taxable() && $cart_item['tax'] > 0 && $cart_item['subtotal'] > 0 ) {
1399
            $item_tax = wpinv_price( wpinv_format_amount( $cart_item['tax'] ), $invoice->get_currency() );
1400
            $tax_rate = !empty( $cart_item['vat_rate'] ) ? $cart_item['vat_rate'] : ( $cart_item['tax'] / $cart_item['subtotal'] ) * 100;
1401
            $tax_rate = $tax_rate > 0 ? (float)wpinv_round_amount( $tax_rate, 4 ) : '';
1402
            $tax_rate = $tax_rate != '' ? ' <span class="tax-rate">(' . $tax_rate . '%)</span>' : '';
1403
        }
1404
        $line_item_tax = $item_tax . $tax_rate;
1405
1406
        if ( $line_item_tax === '' ) {
1407
            $line_item_tax = 0; // Zero tax
1408
        }
1409
1410
        $line_item = '<tr class="item item-' . ( ($count % 2 == 0) ? 'even' : 'odd' ) . '" data-item-id="' . $item_id . '">';
1411
            $line_item .= '<td class="id">' . $item_id . '</td>';
1412
            $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 );
1413
            if ( $summary !== '' ) {
1414
                $line_item .= '<span class="meta">' . wpautop( wp_kses_post( $summary ) ) . '</span>';
1415
            }
1416
            $line_item .= '</td>';
1417
            $line_item .= '<td class="price">' . $item_price . '</td>';
1418
            
1419
            if ( $item_quantities ) {
1420
                if ( count( $cart_items ) == 1 && $quantity <= 1 ) {
1421
                    $can_remove = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $can_remove is dead and can be removed.
Loading history...
1422
                }
1423
                $line_item .= '<td class="qty" data-quantity="' . $quantity . '">&nbsp;&times;&nbsp;' . $quantity . '</td>';
1424
            } else {
1425
                if ( count( $cart_items ) == 1 ) {
1426
                    $can_remove = false;
1427
                }
1428
            }
1429
            $line_item .= '<td class="total">' . $item_subtotal . '</td>';
1430
            
1431
            if ( $use_taxes ) {
1432
                $line_item .= '<td class="tax">' . $line_item_tax . '</td>';
1433
            }
1434
            $line_item .= '<td class="action">';
1435
            if ( !$invoice->is_paid() && !$invoice->is_refunded() ) {
1436
                $line_item .= '<i class="fa fa-remove wpinv-item-remove"></i>';
1437
            }
1438
            $line_item .= '</td>';
1439
        $line_item .= '</tr>';
1440
1441
        echo apply_filters( 'wpinv_admin_line_item', $line_item, $cart_item, $invoice );
1442
1443
        $count++;
1444
    } 
1445
1446
    do_action( 'wpinv_admin_after_line_items', $cart_items, $invoice );
1447
1448
    return ob_get_clean();
1449
}
1450
1451
function wpinv_checkout_form() {
1452
    global $wpi_checkout_id, $invoicing;
1453
1454
    // Set current invoice id.
1455
    $wpi_checkout_id = wpinv_get_invoice_cart_id();
1456
    $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

1456
    $form_action     = esc_url( /** @scrutinizer ignore-type */ wpinv_get_checkout_uri() );
Loading history...
1457
    $payment_form    = wpinv_get_default_payment_form();
1458
1459
    ob_start();
1460
	    do_action( 'wpinv_checkout_content_before' );
1461
1462
        if ( wpinv_get_cart_contents() ) {
1463
1464
            // Get the form elements and items.
1465
	        $elements = $invoicing->form_elements->get_form_elements( $payment_form );
1466
	        $items    = $invoicing->form_elements->convert_checkout_items( wpinv_get_cart_contents(), wpinv_get_invoice_cart() );
1467
            ?>
1468
            <form class="wpinv_payment_form" action="<?php echo $form_action; ?>" method="POST">
1469
                <?php do_action( 'wpinv_main_checkout_form_top' ); ?>
1470
                <input type='hidden' name='form_id' value='<?php echo esc_attr( $payment_form ); ?>'/>
1471
                <input type='hidden' name='invoice_id' value='<?php echo esc_attr( $wpi_checkout_id ); ?>'/>
1472
                    <?php
1473
                        wp_nonce_field( 'wpinv_payment_form', 'wpinv_payment_form' );
1474
                        wp_nonce_field( 'vat_validation', '_wpi_nonce' );
1475
1476
                        foreach ( $elements as $element ) {
1477
                            do_action( 'wpinv_frontend_render_payment_form_element', $element, $items, $payment_form );
1478
                            do_action( "wpinv_frontend_render_payment_form_{$element['type']}", $element, $items, $payment_form );
1479
                        }
1480
                    ?>
1481
                <div class='wpinv_payment_form_errors alert alert-danger d-none'></div>
1482
                <?php do_action( 'wpinv_main_checkout_form_bottom' ); ?>
1483
            </form>
1484
        <?php
1485
1486
        } else {
1487
            do_action( 'wpinv_cart_empty' );
1488
        }
1489
        echo '</div><!--end #wpinv_checkout_wrap-->';
1490
	    do_action( 'wpinv_checkout_content_after' );
1491
        $content = ob_get_clean();
1492
1493
		return str_replace( 'sr-only', '', $content );
1494
}
1495
1496
function wpinv_checkout_cart( $cart_details = array(), $echo = true ) {
1497
    global $ajax_cart_details;
1498
    $ajax_cart_details = $cart_details;
1499
1500
    ob_start();
1501
    do_action( 'wpinv_before_checkout_cart' );
1502
    echo '<div id="wpinv_checkout_cart_form" method="post">';
1503
        echo '<div id="wpinv_checkout_cart_wrap">';
1504
            wpinv_get_template_part( 'wpinv-checkout-cart' );
1505
        echo '</div>';
1506
    echo '</div>';
1507
    do_action( 'wpinv_after_checkout_cart' );
1508
    $content = ob_get_clean();
1509
1510
    if ( $echo ) {
1511
        echo $content;
1512
    } else {
1513
        return $content;
1514
    }
1515
}
1516
add_action( 'wpinv_checkout_cart', 'wpinv_checkout_cart', 10 );
1517
1518
function wpinv_empty_cart_message() {
1519
	return apply_filters( 'wpinv_empty_cart_message', '<span class="wpinv_empty_cart">' . __( 'Your cart is empty.', 'invoicing' ) . '</span>' );
1520
}
1521
1522
/**
1523
 * Echoes the Empty Cart Message
1524
 *
1525
 * @since 1.0
1526
 * @return void
1527
 */
1528
function wpinv_empty_checkout_cart() {
1529
    echo aui()->alert(
1530
        array(
1531
            'type'    => 'warning',
1532
            'content' => wpinv_empty_cart_message(),
1533
        )
1534
    );
1535
}
1536
add_action( 'wpinv_cart_empty', 'wpinv_empty_checkout_cart' );
1537
1538
function wpinv_update_cart_button() {
1539
    if ( !wpinv_item_quantities_enabled() )
1540
        return;
1541
?>
1542
    <input type="submit" name="wpinv_update_cart_submit" class="wpinv-submit wpinv-no-js button" value="<?php _e( 'Update Cart', 'invoicing' ); ?>"/>
1543
    <input type="hidden" name="wpi_action" value="update_cart"/>
1544
<?php
1545
}
1546
1547
function wpinv_checkout_cart_columns() {
1548
    $default = 3;
1549
    if ( wpinv_item_quantities_enabled() ) {
1550
        $default++;
1551
    }
1552
    
1553
    if ( wpinv_use_taxes() ) {
1554
        $default++;
1555
    }
1556
1557
    return apply_filters( 'wpinv_checkout_cart_columns', $default );
1558
}
1559
1560
function wpinv_display_cart_messages() {
1561
    global $wpi_session;
1562
1563
    $messages = $wpi_session->get( 'wpinv_cart_messages' );
1564
1565
    if ( $messages ) {
1566
        foreach ( $messages as $message_id => $message ) {
1567
            // Try and detect what type of message this is
1568
            if ( strpos( strtolower( $message ), 'error' ) ) {
1569
                $type = 'error';
1570
            } elseif ( strpos( strtolower( $message ), 'success' ) ) {
1571
                $type = 'success';
1572
            } else {
1573
                $type = 'info';
1574
            }
1575
1576
            $classes = apply_filters( 'wpinv_' . $type . '_class', array( 'wpinv_errors', 'wpinv-alert', 'wpinv-alert-' . $type ) );
1577
1578
            echo '<div class="' . implode( ' ', $classes ) . '">';
1579
                // Loop message codes and display messages
1580
                    echo '<p class="wpinv_error" id="wpinv_msg_' . $message_id . '">' . $message . '</p>';
1581
            echo '</div>';
1582
        }
1583
1584
        // Remove all of the cart saving messages
1585
        $wpi_session->set( 'wpinv_cart_messages', null );
1586
    }
1587
}
1588
add_action( 'wpinv_before_checkout_cart', 'wpinv_display_cart_messages' );
1589
1590
function wpinv_discount_field() {
1591
    if ( isset( $_GET['wpi-gateway'] ) && wpinv_is_ajax_disabled() ) {
1592
        return; // Only show before a payment method has been selected if ajax is disabled
1593
    }
1594
1595
    if ( !wpinv_is_checkout() ) {
1596
        return;
1597
    }
1598
1599
    if ( wpinv_has_active_discounts() && wpinv_get_cart_total() ) {
1600
    ?>
1601
    <div id="wpinv-discount-field" class="panel panel-default">
1602
        <div class="panel-body">
1603
            <p>
1604
                <label class="wpinv-label" for="wpinv_discount_code"><strong><?php _e( 'Discount', 'invoicing' ); ?></strong></label>
1605
                <span class="wpinv-description"><?php _e( 'Enter a discount code if you have one.', 'invoicing' ); ?></span>
1606
            </p>
1607
            <div class="form-group row">
1608
                <div class="col-sm-4">
1609
                    <input class="wpinv-input form-control" type="text" id="wpinv_discount_code" name="wpinv_discount_code" placeholder="<?php _e( 'Enter discount code', 'invoicing' ); ?>"/>
1610
                </div>
1611
                <div class="col-sm-3">
1612
                    <button id="wpi-apply-discount" type="button" class="btn btn-success btn-sm"><?php _e( 'Apply Discount', 'invoicing' ); ?></button>
1613
                </div>
1614
                <div style="clear:both"></div>
1615
                <div class="col-sm-12 wpinv-discount-msg">
1616
                    <div class="alert alert-success"><i class="fa fa-check-circle"></i><span class="wpi-msg"></span></div>
1617
                    <div class="alert alert-error"><i class="fa fa-warning"></i><span class="wpi-msg"></span></div>
1618
                </div>
1619
            </div>
1620
        </div>
1621
    </div>
1622
<?php
1623
    }
1624
}
1625
add_action( 'wpinv_after_checkout_cart', 'wpinv_discount_field', -10 );
1626
1627
function wpinv_agree_to_terms_js() {
1628
    if ( wpinv_get_option( 'show_agree_to_terms', false ) ) {
1629
?>
1630
<script type="text/javascript">
1631
    jQuery(document).ready(function($){
1632
        $( document.body ).on('click', '.wpinv_terms_links', function(e) {
1633
            //e.preventDefault();
1634
            $('#wpinv_terms').slideToggle();
1635
            $('.wpinv_terms_links').toggle();
1636
            return false;
1637
        });
1638
    });
1639
</script>
1640
<?php
1641
    }
1642
}
1643
add_action( 'wpinv_checkout_form_top', 'wpinv_agree_to_terms_js' );
1644
1645
function wpinv_payment_mode_select( $title ) {
1646
    $gateways = wpinv_get_enabled_payment_gateways( true );
1647
    $gateways = apply_filters( 'wpinv_payment_gateways_on_cart', $gateways );
1648
    $invoice = wpinv_get_invoice( 0, true );
1649
1650
    do_action('wpinv_payment_mode_top');
1651
    $invoice_id = $invoice ? (int)$invoice->ID : 0;
1652
    $chosen_gateway = wpinv_get_chosen_gateway( $invoice_id );
1653
    ?>
1654
    <div id="wpinv_payment_mode_select" data-gateway="<?php echo $chosen_gateway; ?>" <?php echo ( ( $invoice && $invoice->is_free() ) ? 'style="display:none;" data-free="1"' : '' ); ?>>
1655
            <?php do_action( 'wpinv_payment_mode_before_gateways_wrap' ); ?>
1656
            <div id="wpinv-payment-mode-wrap" class="panel panel-default">
1657
                <div class="panel-heading wpi-payment_methods_title">
1658
                    <h6 class="panel-title"><?php echo sanitize_text_field( $title ); ?></h6>
1659
                </div>
1660
                <div class="panel-body wpi-payment_methods">
1661
                    <?php
1662
                    do_action( 'wpinv_payment_mode_before_gateways' );
1663
1664
                    if ( !empty( $gateways ) ) {
1665
                        foreach ( $gateways as $gateway_id => $gateway ) {
1666
                            $checked       = checked( $gateway_id, $chosen_gateway, false );
1667
                            $button_label  = wpinv_get_gateway_button_label( $gateway_id );
1668
                            $gateway_label = wpinv_get_gateway_checkout_label( $gateway_id );
1669
                            $description   = wpinv_get_gateway_description( $gateway_id );
1670
                            ?>
1671
                            <div class="pt-2 pb-2">
1672
                                <div class="radio">
1673
                                    <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>
1674
                                </div>
1675
                                <div style="display:none;" class="payment_box wpi_gateway_<?php echo esc_attr( $gateway_id );?>" role="alert">
1676
                                    <?php if ( !empty( $description ) ) { ?>
1677
                                        <div class="wpi-gateway-desc"><?php _e( $description, 'invoicing' ); ?></div>
1678
                                    <?php } ?>
1679
                                    <?php do_action( 'wpinv_' . $gateway_id . '_cc_form', $invoice_id ) ;?>
1680
                                </div>
1681
                            </div>
1682
                            <?php
1683
                        }
1684
                    } else {
1685
                        echo '<div class="alert alert-danger">'. __( 'No payment gateway active', 'invoicing' ) .'</div>';
1686
                    }
1687
1688
                    do_action( 'wpinv_payment_mode_after_gateways' );
1689
                    ?>
1690
                </div>
1691
            </div>
1692
            <?php do_action( 'wpinv_payment_mode_after_gateways_wrap' ); ?>
1693
    </div>
1694
    <?php
1695
    do_action('wpinv_payment_mode_bottom');
1696
}
1697
add_action( 'wpinv_payment_mode_select', 'wpinv_payment_mode_select' );
1698
1699
function wpinv_checkout_billing_info() {
1700
    if ( wpinv_is_checkout() ) {
1701
        $billing_details    = wpinv_checkout_billing_details();
1702
        $selected_country   = !empty( $billing_details['country'] ) ? $billing_details['country'] : wpinv_default_billing_country();
1703
        ?>
1704
        <div id="wpinv-fields" class="clearfix">
1705
            <div id="wpi-billing" class="wpi-billing clearfix panel panel-default">
1706
                <div class="panel-heading"><h3 class="panel-title"><?php _e( 'Billing Details', 'invoicing' );?></h3></div>
1707
                <div id="wpinv-fields-box" class="panel-body">
1708
                    <?php do_action( 'wpinv_checkout_billing_fields_first', $billing_details ); ?>
1709
                    <p class="wpi-cart-field wpi-col2 wpi-colf">
1710
                        <label for="wpinv_first_name" class="wpi-label"><?php _e( 'First Name', 'invoicing' );?><?php if ( wpinv_get_option( 'fname_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1711
                        <?php
1712
                        echo wpinv_html_text( array(
1713
                                'id'            => 'wpinv_first_name',
1714
                                'name'          => 'wpinv_first_name',
1715
                                'value'         => $billing_details['first_name'],
1716
                                'class'         => 'wpi-input form-control',
1717
                                'placeholder'   => __( 'First name', 'invoicing' ),
1718
                                'required'      => (bool)wpinv_get_option( 'fname_mandatory' ),
1719
                            ) );
1720
                        ?>
1721
                    </p>
1722
                    <p class="wpi-cart-field wpi-col2 wpi-coll">
1723
                        <label for="wpinv_last_name" class="wpi-label"><?php _e( 'Last Name', 'invoicing' );?><?php if ( wpinv_get_option( 'lname_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1724
                        <?php
1725
                        echo wpinv_html_text( array(
1726
                                'id'            => 'wpinv_last_name',
1727
                                'name'          => 'wpinv_last_name',
1728
                                'value'         => $billing_details['last_name'],
1729
                                'class'         => 'wpi-input form-control',
1730
                                'placeholder'   => __( 'Last name', 'invoicing' ),
1731
                                'required'      => (bool)wpinv_get_option( 'lname_mandatory' ),
1732
                            ) );
1733
                        ?>
1734
                    </p>
1735
                    <p class="wpi-cart-field wpi-col2 wpi-colf">
1736
                        <label for="wpinv_address" class="wpi-label"><?php _e( 'Address', 'invoicing' );?><?php if ( wpinv_get_option( 'address_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1737
                        <?php
1738
                        echo wpinv_html_text( array(
1739
                                'id'            => 'wpinv_address',
1740
                                'name'          => 'wpinv_address',
1741
                                'value'         => $billing_details['address'],
1742
                                'class'         => 'wpi-input form-control',
1743
                                'placeholder'   => __( 'Address', 'invoicing' ),
1744
                                'required'      => (bool)wpinv_get_option( 'address_mandatory' ),
1745
                            ) );
1746
                        ?>
1747
                    </p>
1748
                    <p class="wpi-cart-field wpi-col2 wpi-coll">
1749
                        <label for="wpinv_city" class="wpi-label"><?php _e( 'City', 'invoicing' );?><?php if ( wpinv_get_option( 'city_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1750
                        <?php
1751
                        echo wpinv_html_text( array(
1752
                                'id'            => 'wpinv_city',
1753
                                'name'          => 'wpinv_city',
1754
                                'value'         => $billing_details['city'],
1755
                                'class'         => 'wpi-input form-control',
1756
                                'placeholder'   => __( 'City', 'invoicing' ),
1757
                                'required'      => (bool)wpinv_get_option( 'city_mandatory' ),
1758
                            ) );
1759
                        ?>
1760
                    </p>
1761
                    <p id="wpinv_country_box" class="wpi-cart-field wpi-col2 wpi-colf">
1762
                        <label for="wpinv_country" class="wpi-label"><?php _e( 'Country', 'invoicing' );?><?php if ( wpinv_get_option( 'country_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1763
                        <?php echo wpinv_html_select( array(
1764
                            'options'          => wpinv_get_country_list(),
1765
                            'name'             => 'wpinv_country',
1766
                            'id'               => 'wpinv_country',
1767
                            'selected'         => $selected_country,
1768
                            'show_option_all'  => false,
1769
                            'show_option_none' => false,
1770
                            'class'            => 'wpi-input form-control wpi_select2',
1771
                            'placeholder'      => __( 'Choose a country', 'invoicing' ),
1772
                            'required'         => (bool)wpinv_get_option( 'country_mandatory' ),
1773
                        ) ); ?>
1774
                    </p>
1775
                    <p id="wpinv_state_box" class="wpi-cart-field wpi-col2 wpi-coll">
1776
                        <label for="wpinv_state" class="wpi-label"><?php _e( 'State / Province', 'invoicing' );?><?php if ( wpinv_get_option( 'state_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1777
                        <?php
1778
                        $states = wpinv_get_country_states( $selected_country );
1779
                        if( !empty( $states ) ) {
1780
                            echo wpinv_html_select( array(
1781
                                'options'          => $states,
1782
                                'name'             => 'wpinv_state',
1783
                                'id'               => 'wpinv_state',
1784
                                'selected'         => $billing_details['state'],
1785
                                'show_option_all'  => false,
1786
                                'show_option_none' => false,
1787
                                'class'            => 'wpi-input form-control wpi_select2',
1788
                                'placeholder'      => __( 'Choose a state', 'invoicing' ),
1789
                                'required'         => (bool)wpinv_get_option( 'state_mandatory' ),
1790
                            ) );
1791
                        } else {
1792
                            echo wpinv_html_text( array(
1793
                                'name'          => 'wpinv_state',
1794
                                'value'         => $billing_details['state'],
1795
                                'id'            => 'wpinv_state',
1796
                                'class'         => 'wpi-input form-control',
1797
                                'placeholder'   => __( 'State / Province', 'invoicing' ),
1798
                                'required'      => (bool)wpinv_get_option( 'state_mandatory' ),
1799
                            ) );
1800
                        }
1801
                        ?>
1802
                    </p>
1803
                    <p class="wpi-cart-field wpi-col2 wpi-colf">
1804
                        <label for="wpinv_zip" class="wpi-label"><?php _e( 'ZIP / Postcode', 'invoicing' );?><?php if ( wpinv_get_option( 'zip_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1805
                        <?php
1806
                        echo wpinv_html_text( array(
1807
                                'name'          => 'wpinv_zip',
1808
                                'value'         => $billing_details['zip'],
1809
                                'id'            => 'wpinv_zip',
1810
                                'class'         => 'wpi-input form-control',
1811
                                'placeholder'   => __( 'ZIP / Postcode', 'invoicing' ),
1812
                                'required'      => (bool)wpinv_get_option( 'zip_mandatory' ),
1813
                            ) );
1814
                        ?>
1815
                    </p>
1816
                    <p class="wpi-cart-field wpi-col2 wpi-coll">
1817
                        <label for="wpinv_phone" class="wpi-label"><?php _e( 'Phone', 'invoicing' );?><?php if ( wpinv_get_option( 'phone_mandatory' ) ) { echo '<span class="wpi-required">*</span>'; } ?></label>
1818
                        <?php
1819
                        echo wpinv_html_text( array(
1820
                                'id'            => 'wpinv_phone',
1821
                                'name'          => 'wpinv_phone',
1822
                                'value'         => $billing_details['phone'],
1823
                                'class'         => 'wpi-input form-control',
1824
                                'placeholder'   => __( 'Phone', 'invoicing' ),
1825
                                'required'      => (bool)wpinv_get_option( 'phone_mandatory' ),
1826
                            ) );
1827
                        ?>
1828
                    </p>
1829
                    <?php do_action( 'wpinv_checkout_billing_fields_last', $billing_details ); ?>
1830
                    <div class="clearfix"></div>
1831
                </div>
1832
            </div>
1833
            <?php do_action( 'wpinv_after_billing_fields', $billing_details ); ?>
1834
        </div>
1835
        <?php
1836
    }
1837
}
1838
add_action( 'wpinv_checkout_billing_info', 'wpinv_checkout_billing_info' );
1839
1840
function wpinv_checkout_hidden_fields() {
1841
?>
1842
    <?php if ( is_user_logged_in() ) { ?>
1843
    <input type="hidden" name="wpinv_user_id" value="<?php echo get_current_user_id(); ?>"/>
1844
    <?php } ?>
1845
    <input type="hidden" name="wpi_action" value="payment" />
1846
<?php
1847
}
1848
1849
function wpinv_checkout_button_purchase() {
1850
    ob_start();
1851
?>
1852
    <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' ) ?>"/>
1853
<?php
1854
    return apply_filters( 'wpinv_checkout_button_purchase', ob_get_clean() );
1855
}
1856
1857
function wpinv_checkout_total() {
1858
    global $cart_total;
1859
?>
1860
<div id="wpinv_checkout_total" class="panel panel-info">
1861
    <div class="panel-body">
1862
    <?php
1863
    do_action( 'wpinv_purchase_form_before_checkout_total' );
1864
    ?>
1865
    <strong><?php _e( 'Invoice Total:', 'invoicing' ) ?></strong> <span class="wpinv-chdeckout-total"><?php echo $cart_total;?></span>
1866
    <?php
1867
    do_action( 'wpinv_purchase_form_after_checkout_total' );
1868
    ?>
1869
    </div>
1870
</div>
1871
<?php
1872
}
1873
add_action( 'wpinv_checkout_form_bottom', 'wpinv_checkout_total', 9998 );
1874
1875
function wpinv_checkout_submit() {
1876
?>
1877
<div id="wpinv_purchase_submit" class="panel panel-success">
1878
    <div class="panel-body text-center">
1879
    <?php
1880
    do_action( 'wpinv_purchase_form_before_submit' );
1881
    wpinv_checkout_hidden_fields();
1882
    echo wpinv_checkout_button_purchase();
1883
    do_action( 'wpinv_purchase_form_after_submit' );
1884
    ?>
1885
    </div>
1886
</div>
1887
<?php
1888
}
1889
add_action( 'wpinv_checkout_form_bottom', 'wpinv_checkout_submit', 9999 );
1890
1891
function wpinv_receipt_billing_address( $invoice_id = 0 ) {
1892
    $invoice = wpinv_get_invoice( $invoice_id );
1893
1894
    if ( empty( $invoice ) ) {
1895
        return NULL;
1896
    }
1897
1898
    $billing_details = $invoice->get_user_info();
1899
    $address_row = wpinv_get_invoice_address_markup( $billing_details );
1900
1901
    ob_start();
1902
    ?>
1903
    <table class="table table-bordered table-sm wpi-billing-details">
1904
        <tbody>
1905
            <tr class="wpi-receipt-name">
1906
                <th class="text-left"><?php _e( 'Name', 'invoicing' ); ?></th>
1907
                <td><?php echo esc_html( trim( $billing_details['first_name'] . ' ' . $billing_details['last_name'] ) ) ;?></td>
1908
            </tr>
1909
            <tr class="wpi-receipt-email">
1910
                <th class="text-left"><?php _e( 'Email', 'invoicing' ); ?></th>
1911
                <td><?php echo $billing_details['email'] ;?></td>
1912
            </tr>
1913
            <tr class="wpi-receipt-address">
1914
                <th class="text-left"><?php _e( 'Address', 'invoicing' ); ?></th>
1915
                <td><?php echo $address_row ;?></td>
1916
            </tr>
1917
            <?php if ( $billing_details['phone'] ) { ?>
1918
            <tr class="wpi-receipt-phone">
1919
                <th class="text-left"><?php _e( 'Phone', 'invoicing' ); ?></th>
1920
                <td><?php echo esc_html( $billing_details['phone'] ) ;?></td>
1921
            </tr>
1922
            <?php } ?>
1923
        </tbody>
1924
    </table>
1925
    <?php
1926
    $output = ob_get_clean();
1927
    
1928
    $output = apply_filters( 'wpinv_receipt_billing_address', $output, $invoice_id );
1929
1930
    echo $output;
1931
}
1932
1933
function wpinv_filter_success_page_content( $content ) {
1934
    if ( isset( $_GET['payment-confirm'] ) && wpinv_is_success_page() ) {
1935
        if ( has_filter( 'wpinv_payment_confirm_' . sanitize_text_field( $_GET['payment-confirm'] ) ) ) {
1936
            $content = apply_filters( 'wpinv_payment_confirm_' . sanitize_text_field( $_GET['payment-confirm'] ), $content );
1937
        }
1938
    }
1939
1940
    return $content;
1941
}
1942
add_filter( 'the_content', 'wpinv_filter_success_page_content', 99999 );
1943
1944
function wpinv_receipt_actions( $invoice ) {
1945
    if ( !empty( $invoice ) ) {
1946
        $actions = array();
1947
1948
        if ( wpinv_user_can_view_invoice( $invoice->ID ) ) {
1949
            $actions['print']   = array(
1950
                'url'  => $invoice->get_view_url( true ),
1951
                'name' => __( 'Print Invoice', 'invoicing' ),
1952
                'class' => 'btn-primary',
1953
            );
1954
        }
1955
1956
        if ( is_user_logged_in() ) {
1957
            $actions['history'] = array(
1958
                'url'  => wpinv_get_history_page_uri(),
1959
                'name' => __( 'Invoice History', 'invoicing' ),
1960
                'class' => 'btn-warning',
1961
            );
1962
        }
1963
1964
        $actions = apply_filters( 'wpinv_invoice_receipt_actions', $actions, $invoice );
1965
1966
        if ( !empty( $actions ) ) {
1967
        ?>
1968
        <div class="wpinv-receipt-actions text-right">
1969
            <?php foreach ( $actions as $key => $action ) { $class = !empty($action['class']) ? sanitize_html_class( $action['class'] ) : ''; ?>
1970
            <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>
1971
            <?php } ?>
1972
        </div>
1973
        <?php
1974
        }
1975
    }
1976
}
1977
add_action( 'wpinv_receipt_start', 'wpinv_receipt_actions', -10, 1 );
1978
1979
function wpinv_invoice_link( $invoice_id ) {
1980
    $invoice = wpinv_get_invoice( $invoice_id );
1981
1982
    if ( empty( $invoice ) ) {
1983
        return NULL;
1984
    }
1985
1986
    $invoice_link = '<a href="' . esc_url( $invoice->get_view_url() ) . '">' . $invoice->get_number() . '</a>';
1987
1988
    return apply_filters( 'wpinv_get_invoice_link', $invoice_link, $invoice );
1989
}
1990
1991
function wpinv_invoice_subscription_details( $invoice ) {
1992
    if ( !empty( $invoice ) && $invoice->is_recurring() && ! wpinv_is_subscription_payment( $invoice ) ) {
1993
        $subscription = wpinv_get_subscription( $invoice, true );
0 ignored issues
show
Unused Code introduced by
The call to wpinv_get_subscription() has too many arguments starting with true. ( Ignorable by Annotation )

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

1993
        $subscription = /** @scrutinizer ignore-call */ wpinv_get_subscription( $invoice, true );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
1994
1995
        if ( empty( $subscription ) ) {
1996
            return;
1997
        }
1998
1999
        $frequency = WPInv_Subscriptions::wpinv_get_pretty_subscription_frequency($subscription->period, $subscription->frequency);
2000
        $billing = wpinv_price(wpinv_format_amount($subscription->recurring_amount), wpinv_get_invoice_currency_code($subscription->parent_payment_id)) . ' / ' . $frequency;
2001
        $initial = wpinv_price(wpinv_format_amount($subscription->initial_amount), wpinv_get_invoice_currency_code($subscription->parent_payment_id));
2002
2003
        $payments = $subscription->get_child_payments();
2004
        ?>
2005
        <div class="wpinv-subscriptions-details">
2006
            <h3 class="wpinv-subscriptions-t"><?php echo apply_filters( 'wpinv_subscription_details_title', __( 'Subscription Details', 'invoicing' ) ); ?></h3>
2007
            <table class="table">
2008
                <thead>
2009
                    <tr>
2010
                        <th><?php _e( 'Billing Cycle', 'invoicing' ) ;?></th>
2011
                        <th><?php _e( 'Start Date', 'invoicing' ) ;?></th>
2012
                        <th><?php _e( 'Expiration Date', 'invoicing' ) ;?></th>
2013
                        <th class="text-center"><?php _e( 'Times Billed', 'invoicing' ) ;?></th>
2014
                        <th class="text-center"><?php _e( 'Status', 'invoicing' ) ;?></th>
2015
                    </tr>
2016
                </thead>
2017
                <tbody>
2018
                    <tr>
2019
                        <td><?php printf(_x('%s then %s', 'Initial subscription amount then billing cycle and amount', 'invoicing'), $initial, $billing); ?></td>
2020
                        <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

2020
                        <td><?php echo date_i18n(/** @scrutinizer ignore-type */ get_option('date_format'), strtotime($subscription->created, current_time('timestamp'))); ?></td>
Loading history...
2021
                        <td><?php echo date_i18n(get_option('date_format'), strtotime($subscription->expiration, current_time('timestamp'))); ?></td>
2022
                        <td class="text-center"><?php echo $subscription->get_times_billed() . ' / ' . (($subscription->bill_times == 0) ? 'Until Cancelled' : $subscription->bill_times); ?></td>
2023
                        <td class="text-center wpi-sub-status"><?php echo $subscription->get_status_label(); ?></td>
2024
                    </tr>
2025
                </tbody>
2026
            </table>
2027
        </div>
2028
        <?php if ( !empty( $payments ) ) { ?>
2029
        <div class="wpinv-renewal-payments">
2030
            <h3 class="wpinv-renewals-t"><?php echo apply_filters( 'wpinv_renewal_payments_title', __( 'Renewal Payments', 'invoicing' ) ); ?></h3>
2031
            <table class="table">
2032
                <thead>
2033
                    <tr>
2034
                        <th>#</th>
2035
                        <th><?php _e( 'Invoice', 'invoicing' ) ;?></th>
2036
                        <th><?php _e( 'Date', 'invoicing' ) ;?></th>
2037
                        <th class="text-right"><?php _e( 'Amount', 'invoicing' ) ;?></th>
2038
                    </tr>
2039
                </thead>
2040
                <tbody>
2041
                    <?php
2042
                        $i = 1;
2043
                        foreach ( $payments as $payment ) {
2044
                            $invoice_id = $payment->ID;
2045
                    ?>
2046
                    <tr>
2047
                        <th scope="row"><?php echo $i;?></th>
2048
                        <td><?php echo wpinv_invoice_link( $invoice_id ) ;?></td>
2049
                        <td><?php echo wpinv_get_invoice_date( $invoice_id ); ?></td>
2050
                        <td class="text-right"><?php echo wpinv_payment_total( $invoice_id, true ); ?></td>
2051
                    </tr>
2052
                    <?php $i++; } ?>
2053
                </tbody>
2054
            </table>
2055
        </div>
2056
        <?php } ?>
2057
        <?php
2058
    }
2059
}
2060
2061
function wpinv_cart_total_label( $label, $invoice ) {
2062
    if ( empty( $invoice ) ) {
2063
        return $label;
2064
    }
2065
2066
    $prefix_label = '';
2067
    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...
2068
        $prefix_label   = '<span class="label label-primary label-recurring">' . __( 'Recurring Payment', 'invoicing' ) . '</span> ' . wpinv_subscription_payment_desc( $invoice );
2069
    } else if ( $invoice->is_renewal() ) {
2070
        $prefix_label   = '<span class="label label-primary label-renewal">' . __( 'Renewal Payment', 'invoicing' ) . '</span> ';        
2071
    }
2072
2073
    if ( $prefix_label != '' ) {
2074
        $label  = '<span class="wpinv-cart-sub-desc">' . $prefix_label . '</span> ' . $label;
2075
    }
2076
2077
    return $label;
2078
}
2079
add_filter( 'wpinv_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2080
add_filter( 'wpinv_email_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2081
add_filter( 'wpinv_print_cart_total_label', 'wpinv_cart_total_label', 10, 2 );
2082
2083
add_action( 'wpinv_invoice_print_middle', 'wpinv_invoice_subscription_details', 10, 1 );
2084
2085
function wpinv_invoice_print_description( $invoice ) {
2086
    if ( empty( $invoice ) ) {
2087
        return NULL;
2088
    }
2089
    if ( $description = wpinv_get_invoice_description( $invoice->ID ) ) {
2090
        ?>
2091
        <div class="row wpinv-lower">
2092
            <div class="col-sm-12 wpinv-description">
2093
                <?php echo wpautop( $description ); ?>
2094
            </div>
2095
        </div>
2096
        <?php
2097
    }
2098
}
2099
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

2099
add_action( 'wpinv_invoice_print_middle', 'wpinv_invoice_print_description', /** @scrutinizer ignore-type */ 10.1, 1 );
Loading history...
2100
2101
function wpinv_invoice_print_payment_info( $invoice ) {
2102
    if ( empty( $invoice ) ) {
2103
        return NULL;
2104
    }
2105
2106
    if ( $payments_info = wpinv_display_payments_info( $invoice->ID, false ) ) {
2107
        ?>
2108
        <div class="row wpinv-payments">
2109
            <div class="col-sm-12">
2110
                <?php echo $payments_info; ?>
2111
            </div>
2112
        </div>
2113
        <?php 
2114
    }
2115
}
2116
// add_action( 'wpinv_invoice_print_after_line_items', 'wpinv_invoice_print_payment_info', 10, 1 );
2117
2118
function wpinv_get_invoice_note_line_item( $note, $echo = true ) {
2119
    if ( empty( $note ) ) {
2120
        return NULL;
2121
    }
2122
2123
    if ( is_int( $note ) ) {
2124
        $note = get_comment( $note );
2125
    }
2126
2127
    if ( !( is_object( $note ) && is_a( $note, 'WP_Comment' ) ) ) {
2128
        return NULL;
2129
    }
2130
2131
    $note_classes   = array( 'note' );
2132
    $note_classes[] = get_comment_meta( $note->comment_ID, '_wpi_customer_note', true ) ? 'customer-note' : '';
2133
    $note_classes[] = $note->comment_author === 'System' ? 'system-note' : '';
2134
    $note_classes   = apply_filters( 'wpinv_invoice_note_class', array_filter( $note_classes ), $note );
2135
    $note_classes   = !empty( $note_classes ) ? implode( ' ', $note_classes ) : '';
2136
2137
    ob_start();
2138
    ?>
2139
    <li rel="<?php echo absint( $note->comment_ID ) ; ?>" class="<?php echo esc_attr( $note_classes ); ?>">
2140
        <div class="note_content">
2141
            <?php echo wpautop( wptexturize( wp_kses_post( $note->comment_content ) ) ); ?>
2142
        </div>
2143
        <p class="meta">
2144
            <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

2144
            <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...
2145
            <?php if ( is_admin() && ( $note->comment_author !== 'System' || wpinv_current_user_can_manage_invoicing() ) ) { ?>
2146
                <a href="#" class="delete_note"><?php _e( 'Delete note', 'invoicing' ); ?></a>
2147
            <?php } ?>
2148
        </p>
2149
    </li>
2150
    <?php
2151
    $note_content = ob_get_clean();
2152
    $note_content = apply_filters( 'wpinv_get_invoice_note_line_item', $note_content, $note, $echo );
2153
2154
    if ( $echo ) {
2155
        echo $note_content;
2156
    } else {
2157
        return $note_content;
2158
    }
2159
}
2160
2161
function wpinv_invalid_invoice_content() {
2162
    global $post;
2163
2164
    $invoice = wpinv_get_invoice( $post->ID );
2165
2166
    $error = __( 'This invoice is only viewable by clicking on the invoice link that was sent to you via email.', 'invoicing' );
2167
    if ( !empty( $invoice->ID ) && $invoice->has_status( array_keys( wpinv_get_invoice_statuses() ) ) ) {
2168
        if ( is_user_logged_in() ) {
2169
            if ( wpinv_require_login_to_checkout() ) {
2170
                if ( isset( $_GET['invoice_key'] ) && $_GET['invoice_key'] === $invoice->get_key() ) {
2171
                    $error = __( 'You are not allowed to view this invoice.', 'invoicing' );
2172
                }
2173
            }
2174
        } else {
2175
            if ( wpinv_require_login_to_checkout() ) {
2176
                if ( isset( $_GET['invoice_key'] ) && $_GET['invoice_key'] === $invoice->get_key() ) {
2177
                    $error = __( 'You must be logged in to view this invoice.', 'invoicing' );
2178
                }
2179
            }
2180
        }
2181
    } else {
2182
        $error = __( 'This invoice is deleted or does not exist.', 'invoicing' );
2183
    }
2184
    ?>
2185
    <div class="row wpinv-row-invalid">
2186
        <div class="col-md-6 col-md-offset-3 wpinv-message error">
2187
            <h3><?php _e( 'Access Denied', 'invoicing' ); ?></h3>
2188
            <p class="wpinv-msg-text"><?php echo $error; ?></p>
2189
        </div>
2190
    </div>
2191
    <?php
2192
}
2193
add_action( 'wpinv_invalid_invoice_content', 'wpinv_invalid_invoice_content' );
2194
2195
add_action( 'wpinv_checkout_billing_fields_last', 'wpinv_force_company_name_field');
2196
function wpinv_force_company_name_field(){
2197
    $invoice = wpinv_get_invoice_cart();
2198
    $user_id = wpinv_get_user_id( $invoice->ID );
2199
    $company = empty( $user_id ) ? "" : get_user_meta( $user_id, '_wpinv_company', true );
2200
    if ( 1 == wpinv_get_option( 'force_show_company' ) && !wpinv_use_taxes() ) {
2201
        ?>
2202
        <p class="wpi-cart-field wpi-col2 wpi-colf">
2203
            <label for="wpinv_company" class="wpi-label"><?php _e('Company Name', 'invoicing'); ?></label>
2204
            <?php
2205
            echo wpinv_html_text(array(
2206
                'id' => 'wpinv_company',
2207
                'name' => 'wpinv_company',
2208
                'value' => $company,
2209
                'class' => 'wpi-input form-control',
2210
                'placeholder' => __('Company name', 'invoicing'),
2211
                'required'      => true,
2212
            ));
2213
            ?>
2214
        </p>
2215
        <?php
2216
    }
2217
}
2218
2219
/**
2220
 * Function to get privacy policy text.
2221
 *
2222
 * @since 1.0.13
2223
 * @return string
2224
 */
2225
function wpinv_get_policy_text() {
2226
    $privacy_page_id = get_option( 'wp_page_for_privacy_policy', 0 );
2227
2228
    $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]' ));
2229
2230
    if(!$privacy_page_id){
2231
        $privacy_page_id = wpinv_get_option( 'privacy_page', 0 );
2232
    }
2233
2234
    $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

2234
    $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...
2235
2236
    $find_replace = array(
2237
        '[wpinv_privacy_policy]' => $privacy_link,
2238
    );
2239
2240
    $privacy_text = str_replace( array_keys( $find_replace ), array_values( $find_replace ), $text );
2241
2242
    return wp_kses_post(wpautop($privacy_text));
2243
}
2244
2245
2246
/**
2247
 * Allows the user to set their own price for an invoice item
2248
 */
2249
function wpinv_checkout_cart_item_name_your_price( $cart_item, $key ) {
2250
    
2251
    //Ensure we have an item id
2252
    if(! is_array( $cart_item ) || empty( $cart_item['id'] ) ) {
2253
        return;
2254
    }
2255
2256
    //Fetch the item
2257
    $item_id = $cart_item['id'];
2258
    $item    = new WPInv_Item( $item_id );
2259
    
2260
    if(! $item->supports_dynamic_pricing() || !$item->get_is_dynamic_pricing() ) {
2261
        return;
2262
    }
2263
2264
    //Fetch the dynamic pricing "strings"
2265
    $suggested_price_text = esc_html( wpinv_get_option( 'suggested_price_text', __( 'Suggested Price:', 'invoicing' ) ) );
2266
    $minimum_price_text   = esc_html( wpinv_get_option( 'minimum_price_text', __( 'Minimum Price:', 'invoicing' ) ) );
2267
    $name_your_price_text = esc_html( wpinv_get_option( 'name_your_price_text', __( 'Name Your Price', 'invoicing' ) ) );
2268
2269
    //Display a "name_your_price" button
2270
    echo " &mdash; <a href='#' class='wpinv-name-your-price-frontend small'>$name_your_price_text</a></div>";
2271
2272
    //Display a name_your_price form
2273
    echo '<div class="name-your-price-miniform">';
2274
    
2275
    //Maybe display the recommended price
2276
    if( $item->get_price() > 0 && !empty( $suggested_price_text ) ) {
2277
        $suggested_price = $item->get_the_price();
2278
        echo "<div>$suggested_price_text &mdash; $suggested_price</div>";
2279
    }
2280
2281
    //Display the update price form
2282
    $symbol         = wpinv_currency_symbol();
2283
    $position       = wpinv_currency_position();
2284
    $minimum        = esc_attr( $item->get_minimum_price() );
2285
    $price          = esc_attr( $cart_item['item_price'] );
2286
    $update         = esc_attr__( "Update", 'invoicing' );
2287
2288
    //Ensure it supports dynamic prici
2289
    if( $price < $minimum ) {
2290
        $price = $minimum;
2291
    }
2292
2293
    echo '<label>';
2294
    echo $position != 'right' ? $symbol . '&nbsp;' : '';
2295
    echo "<input type='number' min='$minimum' placeholder='$price' value='$price' class='wpi-field-price' />";
2296
    echo $position == 'right' ? '&nbsp;' . $symbol : '' ;
2297
    echo "</label>";
2298
    echo "<input type='hidden' value='$item_id' class='wpi-field-item' />";
2299
    echo "<a class='btn btn-success wpinv-submit wpinv-update-dynamic-price-frontend'>$update</a>";
2300
2301
    //Maybe display the minimum price
2302
    if( $item->get_minimum_price() > 0 && !empty( $minimum_price_text ) ) {
2303
        $minimum_price = wpinv_price( wpinv_format_amount( $item->get_minimum_price() ) );
2304
        echo "<div>$minimum_price_text &mdash; $minimum_price</div>";
2305
    }
2306
2307
    echo "</div>";
2308
2309
}
2310
add_action( 'wpinv_checkout_cart_item_price_after', 'wpinv_checkout_cart_item_name_your_price', 10, 2 );
2311
2312
function wpinv_oxygen_fix_conflict() {
2313
    global $ct_ignore_post_types;
2314
2315
    if ( ! is_array( $ct_ignore_post_types ) ) {
2316
        $ct_ignore_post_types = array();
2317
    }
2318
2319
    $post_types = array( 'wpi_discount', 'wpi_invoice', 'wpi_item' );
2320
2321
    foreach ( $post_types as $post_type ) {
2322
        $ct_ignore_post_types[] = $post_type;
2323
2324
        // Ignore post type
2325
        add_filter( 'pre_option_oxygen_vsb_ignore_post_type_' . $post_type, '__return_true', 999 );
2326
    }
2327
2328
    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

2328
    /** @scrutinizer ignore-call */ 
2329
    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...
2329
    add_filter( 'template_include', 'wpinv_template', 999, 1 );
2330
}
2331
2332
/**
2333
 * Helper function to display a payment form on the frontend.
2334
 */
2335
function getpaid_display_payment_form( $form ) {
2336
    global $invoicing;
2337
2338
    // Ensure that it is published.
2339
	if ( 'publish' != get_post_status( $form ) ) {
2340
		return aui()->alert(
2341
			array(
2342
				'type'    => 'warning',
2343
				'content' => __( 'This payment form is no longer active', 'invoicing' ),
2344
			)
2345
		);
2346
	}
2347
2348
    // Get the form.
2349
    $form = new GetPaid_Payment_Form( $form );
2350
    $html = wpinv_get_template_html( 'payment-forms/form.php', compact( 'form' ) );
2351
    return str_replace( 'sr-only', '', $html );
2352
2353
}
2354
2355
/**
2356
 * Helper function to display a item payment form on the frontend.
2357
 */
2358
function getpaid_display_item_payment_form( $items ) {
2359
    global $invoicing;
2360
2361
    foreach ( array_keys( $items ) as $id ) {
2362
	    if ( 'publish' != get_post_status( $id ) ) {
2363
		    unset( $items[ $id ] );
2364
	    }
2365
    }
2366
2367
    if ( empty( $items ) ) {
2368
		return aui()->alert(
2369
			array(
2370
				'type'    => 'warning',
2371
				'content' => __( 'No published items found', 'invoicing' ),
2372
			)
2373
		);
2374
    }
2375
2376
    $item_key = getpaid_convert_items_to_string( $items );
2377
2378
    // Get the form elements and items.
2379
    $form     = wpinv_get_default_payment_form();
2380
	$elements = $invoicing->form_elements->get_form_elements( $form );
2381
	$items    = $invoicing->form_elements->convert_normal_items( $items );
2382
2383
	ob_start();
2384
	echo "<form class='wpinv_payment_form'>";
2385
	do_action( 'wpinv_payment_form_top' );
2386
    echo "<input type='hidden' name='form_id' value='$form'/>";
2387
    echo "<input type='hidden' name='form_items' value='$item_key'/>";
2388
	wp_nonce_field( 'wpinv_payment_form', 'wpinv_payment_form' );
2389
	wp_nonce_field( 'vat_validation', '_wpi_nonce' );
2390
2391
	foreach ( $elements as $element ) {
2392
		do_action( 'wpinv_frontend_render_payment_form_element', $element, $items, $form );
2393
		do_action( "wpinv_frontend_render_payment_form_{$element['type']}", $element, $items, $form );
2394
	}
2395
2396
	echo "<div class='wpinv_payment_form_errors alert alert-danger d-none'></div>";
2397
	do_action( 'wpinv_payment_form_bottom' );
2398
	echo '</form>';
2399
2400
	$content = ob_get_clean();
2401
	return str_replace( 'sr-only', '', $content );
2402
}
2403
2404
/**
2405
 * Helper function to display an invoice payment form on the frontend.
2406
 */
2407
function getpaid_display_invoice_payment_form( $invoice_id ) {
2408
    global $invoicing;
2409
2410
    $invoice = wpinv_get_invoice( $invoice_id );
2411
2412
    if ( empty( $invoice ) ) {
2413
		return aui()->alert(
2414
			array(
2415
				'type'    => 'warning',
2416
				'content' => __( 'Invoice not found', 'invoicing' ),
2417
			)
2418
		);
2419
    }
2420
2421
    if ( $invoice->is_paid() ) {
2422
		return aui()->alert(
2423
			array(
2424
				'type'    => 'warning',
2425
				'content' => __( 'Invoice has already been paid', 'invoicing' ),
2426
			)
2427
		);
2428
    }
2429
2430
    // Get the form elements and items.
2431
    $form     = wpinv_get_default_payment_form();
2432
	$elements = $invoicing->form_elements->get_form_elements( $form );
2433
	$items    = $invoicing->form_elements->convert_checkout_items( $invoice->cart_details, $invoice );
0 ignored issues
show
Bug Best Practice introduced by
The property cart_details does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
2434
2435
	ob_start();
2436
	echo "<form class='wpinv_payment_form'>";
2437
	do_action( 'wpinv_payment_form_top' );
2438
    echo "<input type='hidden' name='form_id' value='$form'/>";
2439
    echo "<input type='hidden' name='invoice_id' value='$invoice_id'/>";
2440
	wp_nonce_field( 'wpinv_payment_form', 'wpinv_payment_form' );
2441
	wp_nonce_field( 'vat_validation', '_wpi_nonce' );
2442
2443
	foreach ( $elements as $element ) {
2444
		do_action( 'wpinv_frontend_render_payment_form_element', $element, $items, $form );
2445
		do_action( "wpinv_frontend_render_payment_form_{$element['type']}", $element, $items, $form );
2446
	}
2447
2448
	echo "<div class='wpinv_payment_form_errors alert alert-danger d-none'></div>";
2449
	do_action( 'wpinv_payment_form_bottom' );
2450
	echo '</form>';
2451
2452
	$content = ob_get_clean();
2453
	return str_replace( 'sr-only', '', $content );
2454
}
2455
2456
/**
2457
 * Helper function to convert item string to array.
2458
 */
2459
function getpaid_convert_items_to_array( $items ) {
2460
    $items    = array_filter( array_map( 'trim', explode( ',', $items ) ) );
2461
    $prepared = array();
2462
2463
    foreach ( $items as $item ) {
2464
        $data = array_map( 'trim', explode( '|', $item ) );
2465
2466
        if ( empty( $data[0] ) || ! is_numeric( $data[0] ) ) {
2467
            continue;
2468
        }
2469
2470
        $quantity = 1;
2471
        if ( isset( $data[1] ) && is_numeric( $data[1] ) ) {
2472
            $quantity = $data[1];
2473
        }
2474
2475
        $prepared[ $data[0] ] = $quantity;
2476
2477
    }
2478
2479
    return $prepared;
2480
}
2481
2482
/**
2483
 * Helper function to convert item array to string.
2484
 */
2485
function getpaid_convert_items_to_string( $items ) {
2486
    $prepared = array();
2487
2488
    foreach ( $items as $item => $quantity ) {
2489
        $prepared[] = "$item|$quantity";
2490
    }
2491
    return implode( ',', $prepared );
2492
}
2493
2494
/**
2495
 * Helper function to display a payment item.
2496
 * 
2497
 * Provide a label and one of $form, $items or $invoice.
2498
 */
2499
function getpaid_get_payment_button( $label, $form = null, $items = null, $invoice = null ) {
2500
    $label = sanitize_text_field( $label );
2501
    $nonce = wp_create_nonce('getpaid_ajax_form');
2502
2503
    if ( ! empty( $form ) ) {
2504
        $form  = esc_attr( $form );
2505
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-nonce='$nonce' data-form='$form'>$label</button>"; 
2506
    }
2507
	
2508
	if ( ! empty( $items ) ) {
2509
        $items  = esc_attr( $items );
2510
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-nonce='$nonce' data-item='$items'>$label</button>"; 
2511
    }
2512
    
2513
    if ( ! empty( $invoice ) ) {
2514
        $invoice  = esc_attr( $invoice );
2515
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-nonce='$nonce' data-invoice='$invoice'>$label</button>"; 
2516
    }
2517
2518
}
2519
2520
/**
2521
 * Display invoice description before line items.
2522
 *
2523
 * @param WPInv_Invoice $invoice
2524
 */
2525
function getpaid_the_invoice_description( $invoice ) {
2526
    if ( empty( $invoice->description ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The property description does not exist on WPInv_Invoice. Since you implemented __get, consider adding a @property annotation.
Loading history...
2527
        return;
2528
    }
2529
2530
    $description = wp_kses_post( $invoice->description );
2531
    echo "<div style='color: #616161; font-size: 90%; margin-bottom: 20px;'><em>$description</em></div>";
2532
}
2533
add_action( 'wpinv_invoice_print_before_line_items', 'getpaid_the_invoice_description' );
2534
2535
/**
2536
 * Render element on a form.
2537
 *
2538
 * @param array $element
2539
 * @param GetPaid_Payment_Form $form
2540
 */
2541
function getpaid_payment_form_element( $element, $form ) {
2542
2543
    // Set up the args.
2544
    $element_type    = trim( $element['type'] );
2545
    $element['form'] = $form;
2546
    extract( $element );
2547
2548
    // Try to locate the appropriate template.
2549
    $located = wpinv_locate_template( "payment-forms/elements/$element_type.php" );
2550
    
2551
    // Abort if this is not our element.
2552
    if ( empty( $located ) || ! file_exists( $located ) ) {
2553
        return;
2554
    }
2555
2556
    // Generate the class and id of the element.
2557
    $wrapper_class = 'getpaid-payment-form-element-' . trim( esc_attr( $element_type ) );
2558
    $id            = isset( $id ) ? $id : uniqid( 'gp' );
2559
2560
    // Echo the opening wrapper.
2561
    echo "<div class='getpaid-payment-form-element $wrapper_class'>";
2562
2563
    // Fires before displaying a given element type's content.
2564
    do_action( "getpaid_before_payment_form_{$element_type}_element", $element, $form );
2565
2566
    // Include the template for the element.
2567
    include $located;
2568
2569
    // Fires after displaying a given element type's content.
2570
    do_action( "getpaid_payment_form_{$element_type}_element", $element, $form );
2571
2572
    // Echo the closing wrapper.
2573
    echo '</div>';
2574
}
2575
add_action( 'getpaid_payment_form_element', 'getpaid_payment_form_element', 10, 2 );
2576
2577
/**
2578
 * Shows a list of gateways that support recurring payments.
2579
 */
2580
function wpinv_get_recurring_gateways_text() {
2581
    $gateways = array();
2582
2583
    foreach ( wpinv_get_payment_gateways() as $key => $gateway ) {
2584
        if ( wpinv_gateway_support_subscription( $key ) ) {
2585
            $gateways[] = sanitize_text_field( $gateway['admin_label'] );
2586
        }
2587
    }
2588
2589
    if ( empty( $gateways ) ) {
2590
        return "<span class='form-text text-danger'>" . __( 'No active gateway supports subscription payments.', 'invoicing' ) ."</span>";
2591
    }
2592
2593
    return "<span class='form-text text-muted'>" . wp_sprintf( __( 'Subscription payments only supported by: %s', 'invoicing' ), implode( ', ', $gateways ) ) ."</span>";
2594
2595
}
2596