Passed
Push — master ( 99ae46...ecf53c )
by Brian
05:15
created

wpinv_html_month_dropdown()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 31
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 22
c 1
b 1
f 0
nc 2
nop 2
dl 0
loc 31
rs 9.568
1
<?php
2
/**
3
 * Template functions.
4
 *
5
 */
6
7
defined( 'ABSPATH' ) || exit;
8
9
/**
10
 * Displays an invoice.
11
 *
12
 * @param WPInv_Invoice $invoice.
13
 */
14
function getpaid_invoice( $invoice ) {
15
    if ( ! empty( $invoice ) ) {
16
        wpinv_get_template( 'invoice/invoice.php', compact( 'invoice' ) );
17
    }
18
}
19
add_action( 'getpaid_invoice', 'getpaid_invoice', 10 );
20
21
/**
22
 * Displays the invoice footer.
23
 */
24
function getpaid_invoice_footer( $invoice ) {
25
    if ( ! empty( $invoice ) ) {
26
        wpinv_get_template( 'invoice/footer.php', compact( 'invoice' ) );
27
    }
28
}
29
add_action( 'getpaid_invoice_footer', 'getpaid_invoice_footer', 10 );
30
31
/**
32
 * Displays the invoice top bar.
33
 */
34
function getpaid_invoice_header( $invoice ) {
35
    if ( ! empty( $invoice ) ) {
36
        wpinv_get_template( 'invoice/header.php', compact( 'invoice' ) );
37
    }
38
}
39
add_action( 'getpaid_invoice_header', 'getpaid_invoice_header', 10 );
40
41
/**
42
 * Displays actions on the left side of the header.
43
 */
44
function getpaid_invoice_header_left_actions( $invoice ) {
45
    if ( ! empty( $invoice ) ) {
46
        wpinv_get_template( 'invoice/header-left-actions.php', compact( 'invoice' ) );
47
    }
48
}
49
add_action( 'getpaid_invoice_header_left', 'getpaid_invoice_header_left_actions', 10 );
50
51
/**
52
 * Displays actions on the right side of the invoice top bar.
53
 */
54
function getpaid_invoice_header_right_actions( $invoice ) {
55
    if ( ! empty( $invoice ) ) {
56
        wpinv_get_template( 'invoice/header-right-actions.php', compact( 'invoice' ) );
57
    }
58
}
59
add_action( 'getpaid_invoice_header_right', 'getpaid_invoice_header_right_actions', 10 );
60
61
/**
62
 * Displays the invoice title, logo etc.
63
 */
64
function getpaid_invoice_details_top( $invoice ) {
65
    if ( ! empty( $invoice ) ) {
66
        wpinv_get_template( 'invoice/details-top.php', compact( 'invoice' ) );
67
    }
68
}
69
add_action( 'getpaid_invoice_details', 'getpaid_invoice_details_top', 10 );
70
71
/**
72
 * Displays the company logo.
73
 */
74
function getpaid_invoice_logo( $invoice ) {
75
    if ( ! empty( $invoice ) ) {
76
        wpinv_get_template( 'invoice/invoice-logo.php', compact( 'invoice' ) );
77
    }
78
}
79
add_action( 'getpaid_invoice_details_top_left', 'getpaid_invoice_logo' );
80
81
/**
82
 * Displays the type of invoice.
83
 */
84
function getpaid_invoice_type( $invoice ) {
85
    if ( ! empty( $invoice ) ) {
86
        wpinv_get_template( 'invoice/invoice-type.php', compact( 'invoice' ) );
87
    }
88
}
89
add_action( 'getpaid_invoice_details_top_right', 'getpaid_invoice_type' );
90
91
/**
92
 * Displays the invoice details.
93
 */
94
function getpaid_invoice_details_main( $invoice ) {
95
    if ( ! empty( $invoice ) ) {
96
        wpinv_get_template( 'invoice/details.php', compact( 'invoice' ) );
97
    }
98
}
99
add_action( 'getpaid_invoice_details', 'getpaid_invoice_details_main', 50 );
100
101
/**
102
 * Returns a path to the templates directory.
103
 *
104
 * @return string
105
 */
106
function wpinv_get_templates_dir() {
107
    return getpaid_template()->templates_dir;
108
}
109
110
/**
111
 * Returns a url to the templates directory.
112
 *
113
 * @return string
114
 */
115
function wpinv_get_templates_url() {
116
    return getpaid_template()->templates_url;
117
}
118
119
/**
120
 * Displays a template.
121
 *
122
 * First checks if there is a template overide, if not it loads the default template.
123
 *
124
 * @param string $template_name e.g payment-forms/cart.php The template to locate.
125
 * @param string $template_path The templates directory relative to the theme's root dir. Defaults to 'invoicing'.
126
 * @param string $default_path The root path to the default template. Defaults to invoicing/templates
127
 */
128
function wpinv_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
129
    getpaid_template()->display_template( $template_name, $args, $template_path, $default_path );
130
}
131
132
/**
133
 * Retrieves a given template's html code.
134
 *
135
 * First checks if there is a template overide, if not it loads the default template.
136
 *
137
 * @param string $template_name e.g payment-forms/cart.php The template to locate.
138
 * @param array $args An array of args to pass to the template.
139
 * @param string $template_path The templates directory relative to the theme's root dir. Defaults to 'invoicing'.
140
 * @param string $default_path The root path to the default template. Defaults to invoicing/templates
141
 */
142
function wpinv_get_template_html( $template_name, $args = array(), $template_path = '', $default_path = '' ) {
143
	return getpaid_template()->get_template( $template_name, $args, $template_path, $default_path );
144
}
145
146
/**
147
 * Returns the default path from where to look for template overides.
148
 *
149
 * @return string
150
 */
151
function wpinv_template_path() {
152
    return apply_filters( 'wpinv_template_path', wpinv_get_theme_template_dir_name() );
153
}
154
155
/**
156
 * Returns the directory containing the template overides.
157
 *
158
 * @return string
159
 */
160
function wpinv_get_theme_template_dir_name() {
161
	return trailingslashit( apply_filters( 'wpinv_templates_dir', 'invoicing' ) );
162
}
163
164
/**
165
 * Locates a template path.
166
 *
167
 * First checks if there is a template overide, if not it loads the default template.
168
 *
169
 * @param string $template_name e.g payment-forms/cart.php The template to locate.
170
 * @param string $template_path The template path relative to the theme's root dir. Defaults to 'invoicing'.
171
 * @param string $default_path The root path to the default template. Defaults to invoicing/templates
172
 */
173
function wpinv_locate_template( $template_name, $template_path = '', $default_path = '' ) {
174
    return getpaid_template()->locate_template( $template_name, $template_path, $default_path );
175
}
176
177
function wpinv_get_template_part( $slug, $name = null, $load = true ) {
178
	do_action( 'get_template_part_' . $slug, $slug, $name );
179
180
	// Setup possible parts
181
	$templates = array();
182
	if ( isset( $name ) ) {
183
		$templates[] = $slug . '-' . $name . '.php';
184
    }
185
	$templates[] = $slug . '.php';
186
187
	// Allow template parts to be filtered
188
	$templates = apply_filters( 'wpinv_get_template_part', $templates, $slug, $name );
189
190
	// Return the part that is found
191
	return wpinv_locate_tmpl( $templates, $load, false );
192
}
193
194
function wpinv_locate_tmpl( $template_names, $load = false, $require_once = true ) {
195
	// No file found yet
196
	$located = false;
197
198
	// Try to find a template file
199
	foreach ( (array)$template_names as $template_name ) {
200
201
		// Continue if template is empty
202
		if ( empty( $template_name ) ) {
203
			continue;
204
        }
205
206
		// Trim off any slashes from the template name
207
		$template_name = ltrim( $template_name, '/' );
208
209
		// try locating this template file by looping through the template paths
210
		foreach ( wpinv_get_theme_template_paths() as $template_path ) {
211
212
			if ( file_exists( $template_path . $template_name ) ) {
213
				$located = $template_path . $template_name;
214
				break;
215
			}
216
		}
217
218
		if ( ! empty( $located ) ) {
219
			break;
220
		}
221
	}
222
223
	if ( ( true == $load ) && ! empty( $located ) ) {
224
		load_template( $located, $require_once );
225
    }
226
227
	return $located;
228
}
229
230
function wpinv_get_theme_template_paths() {
231
	$template_dir = wpinv_get_theme_template_dir_name();
232
233
	$file_paths = array(
234
		1   => trailingslashit( get_stylesheet_directory() ) . $template_dir,
235
		10  => trailingslashit( get_template_directory() ) . $template_dir,
236
		100 => wpinv_get_templates_dir(),
237
	);
238
239
	$file_paths = apply_filters( 'wpinv_template_paths', $file_paths );
240
241
	// sort the file paths based on priority
242
	ksort( $file_paths, SORT_NUMERIC );
243
244
	return array_map( 'trailingslashit', $file_paths );
245
}
246
247
function wpinv_checkout_meta_tags() {
248
249
	$pages   = array();
250
	$pages[] = wpinv_get_option( 'success_page' );
251
	$pages[] = wpinv_get_option( 'failure_page' );
252
	$pages[] = wpinv_get_option( 'invoice_history_page' );
253
	$pages[] = wpinv_get_option( 'invoice_subscription_page' );
254
255
	if ( ! wpinv_is_checkout() && ! is_page( $pages ) ) {
256
		return;
257
	}
258
259
	echo '<meta name="robots" content="noindex,nofollow" />' . "\n";
260
}
261
add_action( 'wp_head', 'wpinv_checkout_meta_tags' );
262
263
function wpinv_add_body_classes( $class ) {
264
	$classes = (array)$class;
265
266
	if ( wpinv_is_checkout() ) {
267
		$classes[] = 'wpinv-checkout';
268
		$classes[] = 'wpinv-page';
269
	}
270
271
	if ( wpinv_is_success_page() ) {
272
		$classes[] = 'wpinv-success';
273
		$classes[] = 'wpinv-page';
274
	}
275
276
	if ( wpinv_is_failed_transaction_page() ) {
277
		$classes[] = 'wpinv-failed-transaction';
278
		$classes[] = 'wpinv-page';
279
	}
280
281
	if ( wpinv_is_invoice_history_page() ) {
282
		$classes[] = 'wpinv-history';
283
		$classes[] = 'wpinv-page';
284
	}
285
286
	if ( wpinv_is_subscriptions_history_page() ) {
287
		$classes[] = 'wpinv-subscription';
288
		$classes[] = 'wpinv-page';
289
	}
290
291
	if ( wpinv_is_test_mode() ) {
292
		$classes[] = 'wpinv-test-mode';
293
		$classes[] = 'wpinv-page';
294
	}
295
296
	return array_unique( $classes );
297
}
298
add_filter( 'body_class', 'wpinv_add_body_classes' );
299
300
function wpinv_html_select( $args = array() ) {
301
    $defaults = array(
302
        'options'          => array(),
303
        'name'             => null,
304
        'class'            => '',
305
        'id'               => '',
306
        'selected'         => 0,
307
        'placeholder'      => null,
308
        'multiple'         => false,
309
        'show_option_all'  => _x( 'All', 'all dropdown items', 'invoicing' ),
310
        'show_option_none' => _x( 'None', 'no dropdown items', 'invoicing' ),
311
        'data'             => array(),
312
        'onchange'         => null,
313
        'required'         => false,
314
        'disabled'         => false,
315
        'readonly'         => false,
316
    );
317
318
    $args = wp_parse_args( $args, $defaults );
319
320
    $attrs = array(
321
        'name'     => $args['name'],
322
        'id'       => $args['id'],
323
        'class'    => 'wpinv-select ' . implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) ),
324
        'multiple' => ! empty( $args['multiple'] ),
325
        'readonly' => ! empty( $args['readonly'] ),
326
        'disabled' => ! empty( $args['disabled'] ),
327
        'required' => ! empty( $args['required'] ),
328
        'onchange' => ! empty( $args['onchange'] ),
329
    );
330
331
    if ( $args['placeholder'] ) {
332
        $attrs['data-placeholder'] = $args['placeholder'];
333
    }
334
335
    if ( $args['onchange'] ) {
336
        $attrs['onchange'] = $args['onchange'];
337
    }
338
339
    foreach ( $args['data'] as $key => $value ) {
340
        $attrs["data-$key"] = $value;
341
    }
342
343
    echo '<select ';
344
345
    foreach ( $attrs as $attr => $value ) {
346
        
347
        if ( false === $value ) {
348
            continue;
349
        }
350
351
        if ( true === $value ) {
352
            echo ' ' . esc_attr( $attr );
353
        } else {
354
            echo ' ' . esc_attr( $attr ) . '="' . esc_attr( $value ) . '"';
355
        }
356
357
    }
358
359
    echo '>';
360
361
    if ( $args['show_option_all'] ) {
362
        if ( $args['multiple'] ) {
363
            $selected = in_array( 0, $args['selected'] );
364
        } else {
365
            $selected = empty( $args['selected'] );
366
        }
367
        echo '<option value="all"' . selected( $selected, true, false ) . '>' . esc_html( $args['show_option_all'] ) . '</option>';
368
    }
369
370
    if ( ! empty( $args['options'] ) ) {
371
372
        if ( $args['show_option_none'] ) {
373
            if ( $args['multiple'] ) {
374
                $selected = in_array( '', $args['selected'] );
375
            } else {
376
                $selected = $args['selected'] === '';
377
            }
378
379
            echo '<option value=""' . selected( $selected, true, false ) . '>' . esc_html( $args['show_option_none'] ) . '</option>';
380
        }
381
382
        foreach ( $args['options'] as $key => $option ) {
383
384
            if ( $args['multiple'] && is_array( $args['selected'] ) ) {
385
                $selected = in_array( $key, $args['selected'] );
386
            } else {
387
                $selected = $args['selected'] == $key;
388
            }
389
390
            echo '<option value="' . esc_attr( $key ) . '"' . selected( $selected, true, false ) . '>' . esc_html( $option ) . '</option>';
391
        }
392
    }
393
394
    echo '</select>';
395
396
}
397
398
function wpinv_item_dropdown( $args = array() ) {
399
    $defaults = array(
400
        'name'             => 'wpi_item',
401
        'id'               => 'wpi_item',
402
        'class'            => '',
403
        'multiple'         => false,
404
        'selected'         => 0,
405
        'number'           => -1,
406
        'placeholder'      => __( 'Choose a item', 'invoicing' ),
407
        'data'             => array( 'search-type' => 'item' ),
408
        'show_option_all'  => false,
409
        'show_option_none' => false,
410
        'show_recurring'   => false,
411
    );
412
413
    $args = wp_parse_args( $args, $defaults );
414
415
    $item_args = array(
416
        'post_type'      => 'wpi_item',
417
        'orderby'        => 'title',
418
        'order'          => 'ASC',
419
        'posts_per_page' => $args['number'],
420
    );
421
422
    $item_args  = apply_filters( 'wpinv_item_dropdown_query_args', $item_args, $args, $defaults );
423
424
    $items      = get_posts( $item_args );
425
    $options    = array();
426
    if ( $items ) {
427
        foreach ( $items as $item ) {
428
            $title = esc_html( $item->post_title );
429
430
            if ( ! empty( $args['show_recurring'] ) ) {
431
                $title .= wpinv_get_item_suffix( $item->ID, false );
432
            }
433
434
            $options[ absint( $item->ID ) ] = $title;
435
        }
436
    }
437
438
    // This ensures that any selected items are included in the drop down
439
    if ( is_array( $args['selected'] ) ) {
440
        foreach ( $args['selected'] as $item ) {
441
            if ( ! in_array( $item, $options ) ) {
442
                $title = get_the_title( $item );
443
                if ( ! empty( $args['show_recurring'] ) ) {
444
                    $title .= wpinv_get_item_suffix( $item, false );
445
                }
446
                $options[ $item ] = $title;
447
            }
448
        }
449
    } elseif ( is_numeric( $args['selected'] ) && $args['selected'] !== 0 ) {
450
        if ( ! in_array( $args['selected'], $options ) ) {
451
            $title = get_the_title( $args['selected'] );
452
            if ( ! empty( $args['show_recurring'] ) ) {
453
                $title .= wpinv_get_item_suffix( $args['selected'], false );
454
            }
455
            $options[ $args['selected'] ] = get_the_title( $args['selected'] );
456
        }
457
    }
458
459
    wpinv_html_select(
460
        array(
461
			'name'             => $args['name'],
462
			'selected'         => $args['selected'],
463
			'id'               => $args['id'],
464
			'class'            => $args['class'],
465
			'options'          => $options,
466
			'multiple'         => $args['multiple'],
467
			'placeholder'      => $args['placeholder'],
468
			'show_option_all'  => $args['show_option_all'],
469
			'show_option_none' => $args['show_option_none'],
470
			'data'             => $args['data'],
471
        )
472
    );
473
474
}
475
476
/**
477
 * Returns an array of published items.
478
 */
479
function wpinv_get_published_items_for_dropdown() {
480
481
    $items = get_posts(
482
        array(
483
            'post_type'      => 'wpi_item',
484
            'orderby'        => 'title',
485
            'order'          => 'ASC',
486
            'posts_per_page' => '-1',
487
        )
488
    );
489
490
    $options = array();
491
    if ( $items ) {
492
        foreach ( $items as $item ) {
493
            $options[ $item->ID ] = esc_html( $item->post_title ) . wpinv_get_item_suffix( $item->ID, false );
494
        }
495
    }
496
497
    return $options;
498
}
499
500
function wpinv_html_checkbox( $args = array() ) {
501
    $defaults = array(
502
        'name'    => null,
503
        'current' => null,
504
        'class'   => 'wpinv-checkbox',
505
        'options' => array(
506
            'disabled' => false,
507
            'readonly' => false,
508
        ),
509
    );
510
511
    $args = wp_parse_args( $args, $defaults );
512
513
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
514
    $attr  = '';
515
    if ( ! empty( $args['options']['disabled'] ) ) {
516
        $attr .= ' disabled="disabled"';
517
    } elseif ( ! empty( $args['options']['readonly'] ) ) {
518
        $attr .= ' readonly';
519
    }
520
521
    $output = '<input type="checkbox"' . $attr . ' name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['name'] ) . '" class="' . esc_attr( $class ) . ' ' . esc_attr( $args['name'] ) . '" ' . checked( 1, $args['current'], false ) . ' />';
522
523
    return $output;
524
}
525
526
/**
527
 * Displays a hidden field.
528
 */
529
function getpaid_hidden_field( $name, $value ) {
530
    echo "<input type='hidden' name='" . esc_attr( $name ) . "' value=' " . esc_attr( $value ) . "' />";
531
}
532
533
/**
534
 * Displays a submit field.
535
 */
536
function getpaid_submit_field( $value, $name = 'submit', $class = 'btn-primary' ) {
537
    echo "<input type='submit' name='" . esc_attr( $name ) . "' value='" . esc_attr( $value ) . "' class='btn " . esc_attr( $class ) . "' />";
538
}
539
540
function wpinv_html_text( $args = array() ) {
541
    // Backwards compatibility
542
    if ( func_num_args() > 1 ) {
543
        $args = func_get_args();
544
545
        $name  = $args[0];
546
        $value = isset( $args[1] ) ? $args[1] : '';
547
        $label = isset( $args[2] ) ? $args[2] : '';
548
        $desc  = isset( $args[3] ) ? $args[3] : '';
549
    }
550
551
    $defaults = array(
552
        'id'           => '',
553
        'name'         => isset( $name ) ? $name : 'text',
554
        'value'        => isset( $value ) ? $value : null,
555
        'label'        => isset( $label ) ? $label : null,
556
        'desc'         => isset( $desc ) ? $desc : null,
557
        'placeholder'  => '',
558
        'class'        => 'regular-text',
559
        'disabled'     => false,
560
        'readonly'     => false,
561
        'required'     => false,
562
        'autocomplete' => '',
563
        'data'         => false,
564
    );
565
566
    $args = wp_parse_args( $args, $defaults );
567
568
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
569
    $options = '';
570
    if ( $args['required'] ) {
571
        $options .= ' required="required"';
572
    }
573
    if ( $args['readonly'] ) {
574
        $options .= ' readonly';
575
    }
576
    if ( $args['readonly'] ) {
577
        $options .= ' readonly';
578
    }
579
580
    $data = '';
581
    if ( ! empty( $args['data'] ) ) {
582
        foreach ( $args['data'] as $key => $value ) {
583
            $data .= 'data-' . wpinv_sanitize_key( $key ) . '="' . esc_attr( $value ) . '" ';
584
        }
585
    }
586
587
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
588
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['id'] ) . '">' . esc_html( $args['label'] ) . '</label>';
589
    if ( ! empty( $args['desc'] ) ) {
590
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
591
    }
592
593
    $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 ) . '/>';
594
595
    $output .= '</span>';
596
597
    return $output;
598
}
599
600
function wpinv_html_textarea( $args = array() ) {
601
    $defaults = array(
602
        'name'        => 'textarea',
603
        'value'       => null,
604
        'label'       => null,
605
        'desc'        => null,
606
        'class'       => 'large-text',
607
        'disabled'    => false,
608
        'placeholder' => '',
609
    );
610
611
    $args = wp_parse_args( $args, $defaults );
612
613
    $class = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['class'] ) ) );
614
    $disabled = '';
615
    if ( $args['disabled'] ) {
616
        $disabled = ' disabled="disabled"';
617
    }
618
619
    $output = '<span id="wpinv-' . wpinv_sanitize_key( $args['name'] ) . '-wrap">';
620
    $output .= '<label class="wpinv-label" for="' . wpinv_sanitize_key( $args['name'] ) . '">' . esc_html( $args['label'] ) . '</label>';
621
    $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>';
622
623
    if ( ! empty( $args['desc'] ) ) {
624
        $output .= '<span class="wpinv-description">' . esc_html( $args['desc'] ) . '</span>';
625
    }
626
    $output .= '</span>';
627
628
    return $output;
629
}
630
631
function wpinv_html_ajax_user_search( $args = array() ) {
632
    $defaults = array(
633
        'name'         => 'user_id',
634
        'value'        => null,
635
        'placeholder'  => __( 'Enter username', 'invoicing' ),
636
        'label'        => null,
637
        'desc'         => null,
638
        'class'        => '',
639
        'disabled'     => false,
640
        'autocomplete' => 'off',
641
        'data'         => false,
642
    );
643
644
    $args = wp_parse_args( $args, $defaults );
645
646
    $args['class'] = 'wpinv-ajax-user-search ' . $args['class'];
647
648
    $output  = '<span class="wpinv_user_search_wrap">';
649
        $output .= wpinv_html_text( $args );
650
        $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>';
651
    $output .= '</span>';
652
653
    return $output;
654
}
655
656
/**
657
 * Use our template to display invoices.
658
 *
659
 * @param string $template the template that is currently being used.
660
 */
661
function wpinv_template( $template ) {
662
    global $post;
663
664
    if ( ! is_admin() && ( is_single() || is_404() ) && ! empty( $post->ID ) && getpaid_is_invoice_post_type( get_post_type( $post->ID ) ) ) {
665
666
        // If the user can view this invoice, display it.
667
        if ( wpinv_user_can_view_invoice( $post->ID ) ) {
668
669
            return wpinv_get_template_part( 'wpinv-invoice-print', false, false );
670
671
        // Else display an error message.
672
        } else {
673
674
            return wpinv_get_template_part( 'wpinv-invalid-access', false, false );
675
676
        }
677
}
678
679
    return $template;
680
}
681
add_filter( 'template_include', 'wpinv_template', 10, 1 );
682
683
function wpinv_get_business_address() {
684
    $business_address   = wpinv_store_address();
685
    $business_address   = ! empty( $business_address ) ? wp_kses_post( wpautop( $business_address ) ) : '';
686
687
    $business_address = $business_address ? '<div class="address">' . $business_address . '</div>' : '';
688
689
    return apply_filters( 'wpinv_get_business_address', $business_address );
690
}
691
692
/**
693
 * Displays the company address.
694
 */
695
function wpinv_display_from_address() {
696
    wpinv_get_template( 'invoice/company-address.php' );
697
}
698
add_action( 'getpaid_invoice_details_left', 'wpinv_display_from_address', 10 );
699
700
/**
701
 * Generates a watermark text for an invoice.
702
 *
703
 * @param WPInv_Invoice $invoice
704
 * @return string
705
 */
706
function wpinv_watermark( $invoice ) {
707
    $watermark = wpinv_get_watermark( $invoice );
708
    return apply_filters( 'wpinv_get_watermark', $watermark, $invoice );
709
}
710
711
/**
712
 * Generates a watermark text for an invoice.
713
 *
714
 * @param WPInv_Invoice $invoice
715
 * @return string
716
 */
717
function wpinv_get_watermark( $invoice ) {
718
    return $invoice->get_status_nicename();
719
}
720
721
/**
722
 * @deprecated
723
 */
724
function wpinv_display_invoice_details( $invoice ) {
725
    return getpaid_invoice_meta( $invoice );
0 ignored issues
show
Bug introduced by
Are you sure the usage of getpaid_invoice_meta($invoice) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

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

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

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

Loading history...
726
}
727
728
/**
729
 * Displays invoice meta.
730
 */
731
function getpaid_invoice_meta( $invoice ) {
732
733
    $invoice = new WPInv_Invoice( $invoice );
734
735
    // Ensure that we have an invoice.
736
    if ( 0 == $invoice->get_id() ) {
737
        return;
738
    }
739
740
    // Get the invoice meta.
741
    $meta = getpaid_get_invoice_meta( $invoice );
742
743
    // Display the meta.
744
    wpinv_get_template( 'invoice/invoice-meta.php', compact( 'invoice', 'meta' ) );
745
746
}
747
add_action( 'getpaid_invoice_details_right', 'getpaid_invoice_meta', 10 );
748
749
/**
750
 * Retrieves the address markup to use on Invoices.
751
 *
752
 * @since 1.0.13
753
 * @see `wpinv_get_full_address_format`
754
 * @see `wpinv_get_invoice_address_replacements`
755
 * @param array $billing_details customer's billing details
756
 * @param  string $separator How to separate address lines.
757
 * @return string
758
 */
759
function wpinv_get_invoice_address_markup( $billing_details, $separator = '<br/>' ) {
760
761
    // Retrieve the address markup...
762
    $country = empty( $billing_details['country'] ) ? '' : $billing_details['country'];
763
    $format = wpinv_get_full_address_format( $country );
764
765
    // ... and the replacements.
766
    $replacements = wpinv_get_invoice_address_replacements( $billing_details );
767
768
    $formatted_address = str_ireplace( array_keys( $replacements ), $replacements, $format );
769
770
	// Remove unavailable tags.
771
    $formatted_address = preg_replace( '/\{\{\w+\}\}/', '', $formatted_address );
772
773
    // Clean up white space.
774
	$formatted_address = preg_replace( '/  +/', ' ', trim( $formatted_address ) );
775
    $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
776
777
    // Break newlines apart and remove empty lines/trim commas and white space.
778
	$formatted_address = array_filter( array_map( 'wpinv_trim_formatted_address_line', explode( "\n", $formatted_address ) ) );
779
780
    // Add html breaks.
781
	$formatted_address = implode( $separator, $formatted_address );
782
783
	// We're done!
784
	return $formatted_address;
785
786
}
787
788
/**
789
 * Displays the billing address.
790
 *
791
 * @param WPInv_Invoice $invoice
792
 */
793
function wpinv_display_to_address( $invoice = 0 ) {
794
    if ( ! empty( $invoice ) ) {
795
        wpinv_get_template( 'invoice/billing-address.php', compact( 'invoice' ) );
796
    }
797
}
798
add_action( 'getpaid_invoice_details_left', 'wpinv_display_to_address', 40 );
799
800
801
/**
802
 * Displays invoice line items.
803
 */
804
function wpinv_display_line_items( $invoice_id = 0 ) {
805
806
    // Prepare the invoice.
807
    $invoice = new WPInv_Invoice( $invoice_id );
808
809
    // Abort if there is no invoice.
810
    if ( 0 == $invoice->get_id() ) {
811
        return;
812
    }
813
814
    // Line item columns.
815
    $columns = getpaid_invoice_item_columns( $invoice );
816
    $columns = apply_filters( 'getpaid_invoice_line_items_table_columns', $columns, $invoice );
817
818
    wpinv_get_template( 'invoice/line-items.php', compact( 'invoice', 'columns' ) );
819
}
820
add_action( 'getpaid_invoice_line_items', 'wpinv_display_line_items', 10 );
821
822
/**
823
 * Displays invoice subscriptions.
824
 *
825
 * @param WPInv_Invoice $invoice
826
 */
827
function getpaid_display_invoice_subscriptions( $invoice ) {
828
829
    // Subscriptions.
830
	$subscriptions = getpaid_get_invoice_subscriptions( $invoice );
831
832
    if ( empty( $subscriptions ) || ! $invoice->is_recurring() ) {
833
        return;
834
    }
835
836
    $main_subscription = getpaid_get_invoice_subscription( $invoice );
837
838
    // Display related subscriptions.
839
    if ( is_array( $subscriptions ) ) {
0 ignored issues
show
introduced by
The condition is_array($subscriptions) is always false.
Loading history...
840
        printf( '<h2 class="mt-5 mb-1 h4">%s</h2>', esc_html__( 'Related Subscriptions', 'invoicing' ) );
841
        getpaid_admin_subscription_related_subscriptions_metabox( $main_subscription, false );
842
    }
843
844
    if ( $main_subscription->get_total_payments() > 1 ) {
845
        printf( '<h2 class="mt-5 mb-1 h4">%s</h2>', esc_html__( 'Related Invoices', 'invoicing' ) );
846
        getpaid_admin_subscription_invoice_details_metabox( $main_subscription, false );
847
    }
848
849
}
850
add_action( 'getpaid_invoice_line_items', 'getpaid_display_invoice_subscriptions', 55 );
851
add_action( 'wpinv_receipt_end', 'getpaid_display_invoice_subscriptions', 11 );
852
853
/**
854
 * Displays invoice notices on invoices.
855
 */
856
function wpinv_display_invoice_notice() {
857
858
    $label  = wpinv_get_option( 'vat_invoice_notice_label' );
859
    $notice = wpinv_get_option( 'vat_invoice_notice' );
860
861
    if ( empty( $label ) && empty( $notice ) ) {
862
        return;
863
    }
864
865
    echo '<div class="mt-4 mb-4 wpinv-vat-notice">';
866
867
    if ( ! empty( $label ) ) {
868
        $label = esc_html( $label );
869
        echo "<h5>$label</h5>";
870
    }
871
872
    if ( ! empty( $notice ) ) {
873
        echo '<small class="form-text text-muted">' . wp_kses_post( wpautop( wptexturize( $notice ) ) ) . '</small>';
874
    }
875
876
    echo '</div>';
877
}
878
add_action( 'getpaid_invoice_line_items', 'wpinv_display_invoice_notice', 100 );
879
880
/**
881
 * @param WPInv_Invoice $invoice
882
 */
883
function wpinv_display_invoice_notes( $invoice ) {
884
885
    // Retrieve the notes.
886
    $notes = wpinv_get_invoice_notes( $invoice->get_id(), 'customer' );
887
888
    // Abort if we have non.
889
    if ( empty( $notes ) ) {
890
        return;
891
    }
892
893
    // Echo the note.
894
    echo '<div class="getpaid-invoice-notes-wrapper position-relative my-4">';
895
    echo '<h2 class="getpaid-invoice-notes-title mb-1 p-0 h4">' . __( 'Notes', 'invoicing' ) . '</h2>';
896
    echo '<ul class="getpaid-invoice-notes text-break overflow-auto list-unstyled p-0 m-0">';
897
898
    foreach ( $notes as $note ) {
899
        wpinv_get_invoice_note_line_item( $note );
900
    }
901
902
    echo '</ul>';
903
    echo '</div>';
904
}
905
add_action( 'getpaid_invoice_line_items', 'wpinv_display_invoice_notes', 60 );
906
907
/**
908
 * Loads scripts on our invoice templates.
909
 */
910
function wpinv_display_style() {
911
912
    // Make sure that all scripts have been loaded.
913
    if ( ! did_action( 'wp_enqueue_scripts' ) ) {
914
        do_action( 'wp_enqueue_scripts' );
915
    }
916
917
    // Register the invoices style.
918
    wp_register_style( 'wpinv-single-style', WPINV_PLUGIN_URL . 'assets/css/invoice.css', array(), filemtime( WPINV_PLUGIN_DIR . 'assets/css/invoice.css' ) );
919
920
    // Load required styles
921
    wp_print_styles( 'wpinv-single-style' );
922
    wp_print_styles( 'ayecode-ui' );
923
924
    // Maybe load custom css.
925
    $custom_css = wpinv_get_option( 'template_custom_css' );
926
927
    if ( isset( $custom_css ) && ! empty( $custom_css ) ) {
928
        $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

928
        $custom_css     = wp_kses( $custom_css, /** @scrutinizer ignore-type */ array( '\'', '\"' ) );
Loading history...
929
        $custom_css     = str_replace( '&gt;', '>', $custom_css );
930
        echo '<style type="text/css">';
931
        echo wp_kses_post( $custom_css );
932
        echo '</style>';
933
    }
934
935
    wp_site_icon();
936
}
937
add_action( 'wpinv_invoice_print_head', 'wpinv_display_style' );
938
add_action( 'wpinv_invalid_invoice_head', 'wpinv_display_style' );
939
940
941
/**
942
 * Displays the checkout page.
943
 */
944
function wpinv_checkout_form() {
945
    global $wpi_checkout_id;
946
947
    // Retrieve the current invoice.
948
    $invoice_id = getpaid_get_current_invoice_id();
949
950
    if ( empty( $invoice_id ) ) {
951
952
        return aui()->alert(
953
            array(
954
                'type'    => 'warning',
955
                'content' => __( 'Invalid invoice', 'invoicing' ),
956
            )
957
        );
958
959
    }
960
961
    // Can the user view this invoice?
962
    if ( ! wpinv_user_can_view_invoice( $invoice_id ) ) {
963
964
        return aui()->alert(
965
            array(
966
                'type'    => 'warning',
967
                'content' => __( 'You are not allowed to view this invoice', 'invoicing' ),
968
            )
969
        );
970
971
    }
972
973
    // Ensure that it is not yet paid for.
974
    $invoice = new WPInv_Invoice( $invoice_id );
975
976
    // Maybe mark it as viewed.
977
    getpaid_maybe_mark_invoice_as_viewed( $invoice );
978
979
    if ( $invoice->is_paid() ) {
980
981
        return aui()->alert(
982
            array(
983
                'type'    => 'success',
984
                'content' => __( 'This invoice has already been paid.', 'invoicing' ),
985
            )
986
        );
987
988
    }
989
990
    // Set the global invoice id.
991
    $wpi_checkout_id = $invoice_id;
992
993
    // Retrieve appropriate payment form.
994
    $payment_form = new GetPaid_Payment_Form( $invoice->get_meta( 'force_payment_form' ) );
995
    $payment_form = $payment_form->exists() ? $payment_form : new GetPaid_Payment_Form( wpinv_get_default_payment_form() );
996
997
    if ( ! $payment_form->exists() ) {
998
999
        return aui()->alert(
1000
            array(
1001
                'type'    => 'warning',
1002
                'content' => __( 'Error loading the payment form', 'invoicing' ),
1003
            )
1004
        );
1005
1006
    }
1007
1008
    // Set the invoice.
1009
    $payment_form->invoice = $invoice;
1010
1011
    if ( ! $payment_form->is_default() ) {
1012
1013
        $items    = array();
1014
        $item_ids = array();
1015
1016
        foreach ( $invoice->get_items() as $item ) {
1017
            if ( ! in_array( $item->get_id(), $item_ids ) ) {
1018
                $item_ids[] = $item->get_id();
1019
                $items[]    = $item;
1020
            }
1021
        }
1022
1023
        foreach ( $payment_form->get_items() as $item ) {
1024
            if ( ! in_array( $item->get_id(), $item_ids ) ) {
1025
                $item_ids[] = $item->get_id();
1026
                $items[]    = $item;
1027
            }
1028
        }
1029
1030
        $payment_form->set_items( $items );
1031
1032
    } else {
1033
        $payment_form->set_items( $invoice->get_items() );
1034
    }
1035
1036
    // Generate the html.
1037
    return $payment_form->get_html();
1038
1039
}
1040
1041
function wpinv_empty_cart_message() {
1042
	return apply_filters( 'wpinv_empty_cart_message', '<span class="wpinv_empty_cart">' . __( 'Your cart is empty.', 'invoicing' ) . '</span>' );
1043
}
1044
1045
/**
1046
 * Echoes the Empty Cart Message
1047
 *
1048
 * @since 1.0
1049
 * @return void
1050
 */
1051
function wpinv_empty_checkout_cart() {
1052
    aui()->alert(
1053
        array(
1054
            'type'    => 'warning',
1055
            'content' => wpinv_empty_cart_message(),
1056
        ),
1057
        true
1058
    );
1059
}
1060
add_action( 'wpinv_cart_empty', 'wpinv_empty_checkout_cart' );
1061
1062
/**
1063
 * Filters the receipt page.
1064
 */
1065
function wpinv_filter_success_page_content( $content ) {
1066
1067
    // Maybe abort early.
1068
    if ( is_admin() || ! is_singular() || ! in_the_loop() || ! is_main_query() || is_preview() ) {
1069
        return $content;
1070
    }
1071
1072
    // Ensure this is our page.
1073
    if ( isset( $_GET['payment-confirm'] ) && wpinv_is_success_page() ) {
1074
1075
        $gateway = sanitize_text_field( $_GET['payment-confirm'] );
1076
        return apply_filters( "wpinv_payment_confirm_$gateway", $content );
1077
1078
    }
1079
1080
    return $content;
1081
}
1082
add_filter( 'the_content', 'wpinv_filter_success_page_content', 99999 );
1083
1084
function wpinv_invoice_link( $invoice_id ) {
1085
    $invoice = wpinv_get_invoice( $invoice_id );
1086
1087
    if ( empty( $invoice ) ) {
1088
        return null;
1089
    }
1090
1091
    $invoice_link = '<a href="' . esc_url( $invoice->get_view_url() ) . '">' . $invoice->get_number() . '</a>';
1092
1093
    return apply_filters( 'wpinv_get_invoice_link', $invoice_link, $invoice );
1094
}
1095
1096
function wpinv_get_invoice_note_line_item( $note, $echo = true ) {
1097
    if ( empty( $note ) ) {
1098
        return null;
1099
    }
1100
1101
    if ( is_int( $note ) ) {
1102
        $note = get_comment( $note );
1103
    }
1104
1105
    if ( ! ( is_object( $note ) && is_a( $note, 'WP_Comment' ) ) ) {
1106
        return null;
1107
    }
1108
1109
    $note_classes   = array( 'note' );
1110
    $note_classes[] = get_comment_meta( $note->comment_ID, '_wpi_customer_note', true ) ? 'customer-note' : '';
0 ignored issues
show
Bug introduced by
$note->comment_ID of type string is incompatible with the type integer expected by parameter $comment_id of get_comment_meta(). ( Ignorable by Annotation )

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

1110
    $note_classes[] = get_comment_meta( /** @scrutinizer ignore-type */ $note->comment_ID, '_wpi_customer_note', true ) ? 'customer-note' : '';
Loading history...
1111
    $note_classes[] = $note->comment_author === 'System' ? 'system-note' : '';
1112
    $note_classes   = apply_filters( 'wpinv_invoice_note_class', array_filter( $note_classes ), $note );
1113
    $note_classes   = ! empty( $note_classes ) ? implode( ' ', $note_classes ) : '';
1114
1115
    ob_start();
1116
    ?>
1117
    <li rel="<?php echo absint( $note->comment_ID ); ?>" class="<?php echo esc_attr( $note_classes ); ?> mb-2">
1118
        <div class="note_content">
1119
1120
            <?php echo wp_kses_post( wptexturize( $note->comment_content ) ); ?>
1121
1122
            <?php if ( ! is_admin() ) : ?>
1123
                <em class="small form-text text-muted mt-0">
1124
                    <?php
1125
                        printf(
1126
                            __( '%1$s - %2$s at %3$s', 'invoicing' ),
1127
                            $note->comment_author,
1128
                            getpaid_format_date_value( $note->comment_date ),
1129
                            date_i18n( get_option( 'time_format' ), strtotime( $note->comment_date ) )
0 ignored issues
show
Bug introduced by
It seems like get_option('time_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

1129
                            date_i18n( /** @scrutinizer ignore-type */ get_option( 'time_format' ), strtotime( $note->comment_date ) )
Loading history...
1130
                        );
1131
                    ?>
1132
                </em>
1133
            <?php endif; ?>
1134
1135
        </div>
1136
1137
        <?php if ( is_admin() ) : ?>
1138
1139
            <p class="meta px-4 py-2">
1140
                <abbr class="exact-date" title="<?php echo esc_attr( $note->comment_date ); ?>">
1141
                    <?php
1142
                        printf(
1143
                            __( '%1$s - %2$s at %3$s', 'invoicing' ),
1144
                            $note->comment_author,
1145
                            getpaid_format_date_value( $note->comment_date ),
1146
                            date_i18n( get_option( 'time_format' ), strtotime( $note->comment_date ) )
1147
                        );
1148
                    ?>
1149
                </abbr>&nbsp;&nbsp;
1150
                <?php if ( $note->comment_author !== 'System' && wpinv_current_user_can_manage_invoicing() ) { ?>
1151
                    <a href="#" class="delete_note"><?php esc_html_e( 'Delete note', 'invoicing' ); ?></a>
1152
                <?php } ?>
1153
            </p>
1154
1155
        <?php endif; ?>
1156
        
1157
    </li>
1158
    <?php
1159
    $note_content = ob_get_clean();
1160
    $note_content = apply_filters( 'wpinv_get_invoice_note_line_item', $note_content, $note, $echo );
1161
1162
    if ( $echo ) {
1163
        echo wp_kses_post( $note_content );
1164
    } else {
1165
        return $note_content;
1166
    }
1167
}
1168
1169
/**
1170
 * Function to get privacy policy text.
1171
 *
1172
 * @since 1.0.13
1173
 * @return string
1174
 */
1175
function wpinv_get_policy_text() {
1176
    $privacy_page_id = get_option( 'wp_page_for_privacy_policy', 0 );
1177
1178
    $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]' ) );
1179
1180
    if ( ! $privacy_page_id ) {
1181
        $privacy_page_id = wpinv_get_option( 'privacy_page', 0 );
1182
    }
1183
1184
    $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

1184
    $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...
1185
1186
    $find_replace = array(
1187
        '[wpinv_privacy_policy]' => $privacy_link,
1188
    );
1189
1190
    $privacy_text = str_replace( array_keys( $find_replace ), array_values( $find_replace ), $text );
1191
1192
    return wp_kses_post( wpautop( $privacy_text ) );
1193
}
1194
1195
function wpinv_oxygen_fix_conflict() {
1196
    global $ct_ignore_post_types;
1197
1198
    if ( ! is_array( $ct_ignore_post_types ) ) {
1199
        $ct_ignore_post_types = array();
1200
    }
1201
1202
    $post_types = array( 'wpi_discount', 'wpi_invoice', 'wpi_item', 'wpi_payment_form' );
1203
1204
    foreach ( $post_types as $post_type ) {
1205
        $ct_ignore_post_types[] = $post_type;
1206
1207
        // Ignore post type
1208
        add_filter( 'pre_option_oxygen_vsb_ignore_post_type_' . $post_type, '__return_true', 999 );
1209
    }
1210
1211
    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

1211
    /** @scrutinizer ignore-call */ 
1212
    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...
1212
    add_filter( 'template_include', 'wpinv_template', 999, 1 );
1213
}
1214
1215
/**
1216
 * Helper function to display a payment form on the frontend.
1217
 *
1218
 * @param GetPaid_Payment_Form $form
1219
 */
1220
function getpaid_display_payment_form( $form ) {
1221
1222
    if ( is_numeric( $form ) ) {
0 ignored issues
show
introduced by
The condition is_numeric($form) is always false.
Loading history...
1223
        $form = new GetPaid_Payment_Form( $form );
1224
    }
1225
1226
    $form->display();
1227
1228
}
1229
1230
/**
1231
 * Helper function to display a item payment form on the frontend.
1232
 */
1233
function getpaid_display_item_payment_form( $items ) {
1234
1235
    $form = new GetPaid_Payment_Form( wpinv_get_default_payment_form() );
1236
    $form->set_items( $items );
1237
1238
    if ( 0 == count( $form->get_items() ) ) {
1239
        aui()->alert(
1240
			array(
1241
				'type'    => 'warning',
1242
				'content' => __( 'No published items found', 'invoicing' ),
1243
            ),
1244
            true
1245
        );
1246
        return;
1247
    }
1248
1249
    $extra_items     = esc_attr( getpaid_convert_items_to_string( $items ) );
1250
    $extra_items_key = md5( NONCE_KEY . AUTH_KEY . $extra_items );
1251
    $extra_items     = "<input type='hidden' name='getpaid-form-items' value='$extra_items' />";
1252
    $extra_items    .= "<input type='hidden' name='getpaid-form-items-key' value='$extra_items_key' />";
1253
1254
    $form->display( $extra_items );
1255
}
1256
1257
/**
1258
 * Helper function to display an invoice payment form on the frontend.
1259
 */
1260
function getpaid_display_invoice_payment_form( $invoice_id ) {
1261
1262
    $invoice = wpinv_get_invoice( $invoice_id );
1263
1264
    if ( empty( $invoice ) ) {
1265
		aui()->alert(
1266
			array(
1267
				'type'    => 'warning',
1268
				'content' => __( 'Invoice not found', 'invoicing' ),
1269
            ),
1270
            true
1271
        );
1272
        return;
1273
    }
1274
1275
    if ( $invoice->is_paid() ) {
1276
		aui()->alert(
1277
			array(
1278
				'type'    => 'warning',
1279
				'content' => __( 'Invoice has already been paid', 'invoicing' ),
1280
            ),
1281
            true
1282
        );
1283
        return;
1284
    }
1285
1286
    $form = new GetPaid_Payment_Form( wpinv_get_default_payment_form() );
1287
    $form->set_items( $invoice->get_items() );
1288
1289
    $form->display();
1290
}
1291
1292
/**
1293
 * Helper function to convert item string to array.
1294
 */
1295
function getpaid_convert_items_to_array( $items ) {
1296
    $items    = array_filter( array_map( 'trim', explode( ',', $items ) ) );
1297
    $prepared = array();
1298
1299
    foreach ( $items as $item ) {
1300
        $data = array_map( 'trim', explode( '|', $item ) );
1301
1302
        if ( empty( $data[0] ) || ! is_numeric( $data[0] ) ) {
1303
            continue;
1304
        }
1305
1306
        $quantity = 1;
1307
        if ( isset( $data[1] ) && is_numeric( $data[1] ) ) {
1308
            $quantity = (float) $data[1];
1309
        }
1310
1311
        $prepared[ $data[0] ] = $quantity;
1312
1313
    }
1314
1315
    return $prepared;
1316
}
1317
1318
/**
1319
 * Helper function to convert item array to string.
1320
 */
1321
function getpaid_convert_items_to_string( $items ) {
1322
    $prepared = array();
1323
1324
    foreach ( $items as $item => $quantity ) {
1325
        $prepared[] = "$item|$quantity";
1326
    }
1327
    return implode( ',', $prepared );
1328
}
1329
1330
/**
1331
 * Helper function to display a payment item.
1332
 *
1333
 * Provide a label and one of $form, $items or $invoice.
1334
 */
1335
function getpaid_get_payment_button( $label, $form = null, $items = null, $invoice = null ) {
1336
    $label = sanitize_text_field( $label );
1337
1338
    if ( ! empty( $form ) ) {
1339
        $form  = esc_attr( $form );
1340
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-form='$form'>$label</button>";
1341
    }
1342
1343
	if ( ! empty( $items ) ) {
1344
        $items  = esc_attr( $items );
1345
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-item='$items'>$label</button>";
1346
    }
1347
1348
    if ( ! empty( $invoice ) ) {
1349
        $invoice  = esc_attr( $invoice );
1350
        return "<button class='btn btn-primary getpaid-payment-button' type='button' data-invoice='$invoice'>$label</button>";
1351
    }
1352
1353
}
1354
1355
/**
1356
 * Display invoice description before line items.
1357
 *
1358
 * @param WPInv_Invoice $invoice
1359
 */
1360
function getpaid_the_invoice_description( $invoice ) {
1361
    $description = $invoice->get_description();
1362
1363
    if ( empty( $description ) ) {
1364
        return;
1365
    }
1366
1367
    $description = wp_kses_post( wpautop( $description ) );
1368
    echo "<small class='getpaid-invoice-description text-dark p-2 form-text' style='margin-bottom: 20px; border-left: 2px solid #2196F3;'><em>$description</em></small>";
1369
}
1370
add_action( 'getpaid_invoice_line_items', 'getpaid_the_invoice_description', 100 );
1371
add_action( 'wpinv_email_billing_details', 'getpaid_the_invoice_description', 100 );
1372
1373
/**
1374
 * Render element on a form.
1375
 *
1376
 * @param array $element
1377
 * @param GetPaid_Payment_Form $form
1378
 */
1379
function getpaid_payment_form_element( $element, $form ) {
1380
1381
    // Set up the args.
1382
    $element_type    = trim( $element['type'] );
1383
    $element['form'] = $form;
1384
    extract( $element );
1385
1386
    // Try to locate the appropriate template.
1387
    $located = wpinv_locate_template( "payment-forms/elements/$element_type.php" );
1388
1389
    // Abort if this is not our element.
1390
    if ( empty( $located ) || ! file_exists( $located ) ) {
1391
        return;
1392
    }
1393
1394
    // Generate the class and id of the element.
1395
    $wrapper_class = 'getpaid-payment-form-element-' . trim( esc_attr( $element_type ) );
1396
    $id            = isset( $id ) ? $id : uniqid( 'gp' );
1397
1398
    // Echo the opening wrapper.
1399
    echo "<div class='getpaid-payment-form-element $wrapper_class'>";
1400
1401
    // Fires before displaying a given element type's content.
1402
    do_action( "getpaid_before_payment_form_{$element_type}_element", $element, $form );
1403
1404
    // Include the template for the element.
1405
    include $located;
1406
1407
    // Fires after displaying a given element type's content.
1408
    do_action( "getpaid_payment_form_{$element_type}_element", $element, $form );
1409
1410
    // Echo the closing wrapper.
1411
    echo '</div>';
1412
}
1413
add_action( 'getpaid_payment_form_element', 'getpaid_payment_form_element', 10, 2 );
1414
1415
/**
1416
 * Render an element's edit page.
1417
 *
1418
 * @param WP_Post $post
1419
 */
1420
function getpaid_payment_form_edit_element_template( $post ) {
1421
1422
    // Retrieve all elements.
1423
    $all_elements = wp_list_pluck( wpinv_get_data( 'payment-form-elements' ), 'type' );
1424
1425
    foreach ( $all_elements as $element ) {
1426
1427
        // Try to locate the appropriate template.
1428
        $element = esc_attr( sanitize_key( $element ) );
1429
        $located = wpinv_locate_template( "payment-forms-admin/edit/$element.php" );
1430
1431
        // Continue if this is not our element.
1432
        if ( empty( $located ) || ! file_exists( $located ) ) {
1433
            continue;
1434
        }
1435
1436
        // Include the template for the element.
1437
        echo "<div v-if=\"active_form_element.type=='$element'\">";
1438
        include $located;
1439
        echo '</div>';
1440
    }
1441
1442
}
1443
add_action( 'getpaid_payment_form_edit_element_template', 'getpaid_payment_form_edit_element_template' );
1444
1445
/**
1446
 * Render an element's preview.
1447
 *
1448
 */
1449
function getpaid_payment_form_render_element_preview_template() {
1450
1451
    // Retrieve all elements.
1452
    $all_elements = wp_list_pluck( wpinv_get_data( 'payment-form-elements' ), 'type' );
1453
1454
    foreach ( $all_elements as $element ) {
1455
1456
        // Try to locate the appropriate template.
1457
        $element = sanitize_key( $element );
1458
        $located = wpinv_locate_template( "payment-forms-admin/previews/$element.php" );
1459
1460
        // Continue if this is not our element.
1461
        if ( empty( $located ) || ! file_exists( $located ) ) {
1462
            continue;
1463
        }
1464
1465
        // Include the template for the element.
1466
        echo "<div v-if=\"form_element.type=='$element'\">";
1467
        include $located;
1468
        echo '</div>';
1469
    }
1470
1471
}
1472
add_action( 'wpinv_payment_form_render_element_template', 'getpaid_payment_form_render_element_preview_template' );
1473
1474
/**
1475
 * Shows a list of gateways that support recurring payments.
1476
 */
1477
function wpinv_get_recurring_gateways_text() {
1478
    $gateways = array();
1479
1480
    foreach ( wpinv_get_payment_gateways() as $key => $gateway ) {
1481
        if ( wpinv_gateway_support_subscription( $key ) ) {
1482
            $gateways[] = sanitize_text_field( $gateway['admin_label'] );
1483
        }
1484
    }
1485
1486
    if ( empty( $gateways ) ) {
1487
        return "<span class='form-text text-danger'>" . __( 'No active gateways support subscription payments.', 'invoicing' ) . '</span>';
1488
    }
1489
1490
    return "<span class='form-text text-muted'>" . wp_sprintf( __( 'Subscription payments only supported by: %s', 'invoicing' ), implode( ', ', $gateways ) ) . '</span>';
1491
1492
}
1493
1494
/**
1495
 * Returns the template.
1496
 *
1497
 * @return GetPaid_Template
1498
 */
1499
function getpaid_template() {
1500
    return getpaid()->get( 'template' );
1501
}
1502
1503
/**
1504
 * Displays pagination links.
1505
 *
1506
 * @param array args
0 ignored issues
show
Bug introduced by
The type args was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
1507
 * @return string
1508
 */
1509
function getpaid_paginate_links( $args ) {
1510
    return str_replace( 'page-link dots', 'page-link text-dark', aui()->pagination( $args ) );
1511
}
1512
1513
/**
1514
 * Displays the states select markup.
1515
 *
1516
 * @param string country
1517
 * @param string state
0 ignored issues
show
Bug introduced by
The type state was not found. Maybe you did not declare it correctly or list all dependencies?

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

filter:
    dependency_paths: ["lib/*"]

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

Loading history...
1518
 * @return string
1519
 */
1520
function getpaid_get_states_select_markup( $country, $state, $placeholder, $label, $help_text, $required = false, $wrapper_class = 'col-12', $field_name = 'wpinv_state', $echo = false ) {
1521
1522
    $states = wpinv_get_country_states( $country );
1523
    $uniqid = uniqid( '_' );
1524
1525
    if ( ! empty( $states ) ) {
1526
1527
        return aui()->select(
1528
            array(
1529
				'options'          => $states,
1530
				'name'             => esc_attr( $field_name ),
1531
				'id'               => sanitize_html_class( $field_name ) . $uniqid,
1532
				'value'            => sanitize_text_field( $state ),
1533
				'placeholder'      => $placeholder,
1534
				'required'         => $required,
1535
				'label'            => wp_kses_post( $label ),
1536
				'label_type'       => 'vertical',
1537
				'help_text'        => $help_text,
1538
				'class'            => 'getpaid-address-field wpinv_state',
1539
				'wrap_class'       => "$wrapper_class getpaid-address-field-wrapper__state",
1540
				'label_class'      => 'getpaid-address-field-label getpaid-address-field-label__state',
1541
				'extra_attributes' => array(
1542
					'autocomplete' => 'address-level1',
1543
				),
1544
            ),
1545
            $echo
1546
        );
1547
1548
    }
1549
1550
    return aui()->input(
1551
        array(
1552
            'name'             => esc_attr( $field_name ),
1553
            'id'               => sanitize_html_class( $field_name ) . $uniqid,
1554
            'placeholder'      => $placeholder,
1555
            'required'         => $required,
1556
            'label'            => wp_kses_post( $label ),
1557
            'label_type'       => 'vertical',
1558
            'help_text'        => $help_text,
1559
            'value'            => sanitize_text_field( $state ),
1560
            'class'            => 'getpaid-address-field wpinv_state',
1561
            'wrap_class'       => "$wrapper_class getpaid-address-field-wrapper__state",
1562
            'label_class'      => 'getpaid-address-field-label getpaid-address-field-label__state',
1563
            'extra_attributes' => array(
1564
                'autocomplete' => 'address-level1',
1565
            ),
1566
        ),
1567
        $echo
1568
    );
1569
1570
}
1571
1572
/**
1573
 * Retrieves an element's grid width.
1574
 *
1575
 * @param array $element
1576
 * @return string
1577
 */
1578
function getpaid_get_form_element_grid_class( $element ) {
1579
1580
    $class = 'col-12';
1581
    $width = empty( $element['grid_width'] ) ? 'full' : $element['grid_width'];
1582
1583
    if ( $width == 'half' ) {
1584
        $class .= ' col-md-6';
1585
    }
1586
1587
    if ( $width == 'third' ) {
1588
        $class .= ' col-md-4';
1589
    }
1590
1591
    return $class;
1592
}
1593
1594
/**
1595
 * Retrieves the payment form embed URL.
1596
 *
1597
 * @param int $payment_form payment form.
1598
 * @param string $items form items.
1599
 *
1600
 * @return string
1601
 */
1602
function getpaid_embed_url( $payment_form = false, $items = false ) {
1603
1604
    return add_query_arg(
1605
        array(
1606
            'getpaid_embed' => 1,
1607
            'form'          => $payment_form ? absint( $payment_form ) : false,
1608
            'item'          => $items ? urlencode( $items ) : false,
1609
        ),
1610
        home_url( 'index.php' )
1611
    );
1612
1613
}
1614
1615
/**
1616
 * Embeds a payment form.
1617
 *
1618
 * @return string
1619
 */
1620
function getpaid_filter_embed_template( $template ) {
1621
1622
    if ( isset( $_GET['getpaid_embed'] ) ) {
1623
        wpinv_get_template( 'payment-forms/embed.php' );
1624
        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...
1625
    }
1626
1627
    return $template;
1628
}
1629
add_filter( 'template_include', 'getpaid_filter_embed_template' );
1630