Passed
Pull Request — master (#275)
by Brian
06:25
created

wpinv_checkout_fields_callback()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
// MUST have WordPress.
3
if ( !defined( 'WPINC' ) ) {
4
    exit( 'Do NOT access this file directly: ' . basename( __FILE__ ) );
5
}
6
7
function wpinv_get_option( $key = '', $default = false ) {
8
    global $wpinv_options;
9
10
    $value = isset( $wpinv_options[ $key ] ) ? $wpinv_options[ $key ] : $default;
11
    $value = apply_filters( 'wpinv_get_option', $value, $key, $default );
12
13
    return apply_filters( 'wpinv_get_option_' . $key, $value, $key, $default );
14
}
15
16
function wpinv_update_option( $key = '', $value = false ) {
17
    // If no key, exit
18
    if ( empty( $key ) ) {
19
        return false;
20
    }
21
22
    if ( empty( $value ) ) {
23
        $remove_option = wpinv_delete_option( $key );
24
        return $remove_option;
25
    }
26
27
    // First let's grab the current settings
28
    $options = get_option( 'wpinv_settings' );
29
30
    // Let other plugin alter the value
31
    $value = apply_filters( 'wpinv_update_option', $value, $key );
32
33
    // Next let's try to update the value
34
    $options[ $key ] = $value;
35
    $did_update = update_option( 'wpinv_settings', $options );
36
37
    // If it's updated, let's update the global variable
38
    if ( $did_update ) {
39
        global $wpinv_options;
40
        $wpinv_options[ $key ] = $value;
41
    }
42
43
    return $did_update;
44
}
45
46
function wpinv_delete_option( $key = '' ) {
47
    // If no key, exit
48
    if ( empty( $key ) ) {
49
        return false;
50
    }
51
52
    // First let's grab the current settings
53
    $options = get_option( 'wpinv_settings' );
54
55
    // Next let's try to update the value
56
    if( isset( $options[ $key ] ) ) {
57
        unset( $options[ $key ] );
58
    }
59
60
    $did_update = update_option( 'wpinv_settings', $options );
61
62
    // If it updated, let's update the global variable
63
    if ( $did_update ){
64
        global $wpinv_options;
65
        $wpinv_options = $options;
66
    }
67
68
    return $did_update;
69
}
70
71
function wpinv_get_settings() {
72
    $settings = get_option( 'wpinv_settings' );
73
74
    if ( empty( $settings ) ) {
75
        // Update old settings with new single option
76
        $general_settings   = is_array( get_option( 'wpinv_settings_general' ) )    ? get_option( 'wpinv_settings_general' )    : array();
77
        $gateways_settings  = is_array( get_option( 'wpinv_settings_gateways' ) )   ? get_option( 'wpinv_settings_gateways' )   : array();
78
        $checkout_settings  = is_array( get_option( 'wpinv_settings_checkout' ) )   ? get_option( 'wpinv_settings_checkout' )   : array();
79
        $email_settings     = is_array( get_option( 'wpinv_settings_emails' ) )     ? get_option( 'wpinv_settings_emails' )     : array();
80
        $tax_settings       = is_array( get_option( 'wpinv_settings_taxes' ) )      ? get_option( 'wpinv_settings_taxes' )      : array();
81
        $misc_settings      = is_array( get_option( 'wpinv_settings_misc' ) )       ? get_option( 'wpinv_settings_misc' )       : array();
82
        $tool_settings      = is_array( get_option( 'wpinv_settings_tools' ) )      ? get_option( 'wpinv_settings_tools' )      : array();
83
84
        $settings = array_merge( $general_settings, $gateways_settings, $checkout_settings, $email_settings, $tax_settings, $misc_settings, $tool_settings );
0 ignored issues
show
Bug introduced by
It seems like $gateways_settings can also be of type false; however, parameter $array2 of array_merge() does only seem to accept array|null, 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

84
        $settings = array_merge( $general_settings, /** @scrutinizer ignore-type */ $gateways_settings, $checkout_settings, $email_settings, $tax_settings, $misc_settings, $tool_settings );
Loading history...
Bug introduced by
It seems like $general_settings can also be of type false; however, parameter $array1 of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

84
        $settings = array_merge( /** @scrutinizer ignore-type */ $general_settings, $gateways_settings, $checkout_settings, $email_settings, $tax_settings, $misc_settings, $tool_settings );
Loading history...
Bug introduced by
It seems like $checkout_settings can also be of type false; however, parameter $_ of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

84
        $settings = array_merge( $general_settings, $gateways_settings, /** @scrutinizer ignore-type */ $checkout_settings, $email_settings, $tax_settings, $misc_settings, $tool_settings );
Loading history...
85
86
        update_option( 'wpinv_settings', $settings );
87
88
    }
89
    return apply_filters( 'wpinv_get_settings', $settings );
90
}
91
92
function wpinv_register_settings() {
93
    if ( false == get_option( 'wpinv_settings' ) ) {
94
        add_option( 'wpinv_settings' );
95
    }
96
    
97
    $register_settings = wpinv_get_registered_settings();
98
    
99
    foreach ( $register_settings as $tab => $sections ) {
100
        foreach ( $sections as $section => $settings) {
101
            // Check for backwards compatibility
102
            $section_tabs = wpinv_get_settings_tab_sections( $tab );
103
            if ( ! is_array( $section_tabs ) || ! array_key_exists( $section, $section_tabs ) ) {
104
                $section = 'main';
105
                $settings = $sections;
106
            }
107
108
            add_settings_section(
109
                'wpinv_settings_' . $tab . '_' . $section,
110
                __return_null(),
0 ignored issues
show
Bug introduced by
Are you sure the usage of __return_null() 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...
111
                '__return_false',
112
                'wpinv_settings_' . $tab . '_' . $section
113
            );
114
115
            foreach ( $settings as $option ) {
116
                // For backwards compatibility
117
                if ( empty( $option['id'] ) ) {
118
                    continue;
119
                }
120
121
                $name = isset( $option['name'] ) ? $option['name'] : '';
122
123
                add_settings_field(
124
                    'wpinv_settings[' . $option['id'] . ']',
125
                    $name,
126
                    function_exists( 'wpinv_' . $option['type'] . '_callback' ) ? 'wpinv_' . $option['type'] . '_callback' : 'wpinv_missing_callback',
127
                    'wpinv_settings_' . $tab . '_' . $section,
128
                    'wpinv_settings_' . $tab . '_' . $section,
129
                    array(
130
                        'section'     => $section,
131
                        'id'          => isset( $option['id'] )          ? $option['id']          : null,
132
                        'desc'        => ! empty( $option['desc'] )      ? $option['desc']        : '',
133
                        'name'        => isset( $option['name'] )        ? $option['name']        : null,
134
                        'size'        => isset( $option['size'] )        ? $option['size']        : null,
135
                        'options'     => isset( $option['options'] )     ? $option['options']     : '',
136
                        'selected'    => isset( $option['selected'] )    ? $option['selected']    : null,
137
                        'std'         => isset( $option['std'] )         ? $option['std']         : '',
138
                        'min'         => isset( $option['min'] )         ? $option['min']         : null,
139
                        'max'         => isset( $option['max'] )         ? $option['max']         : null,
140
                        'step'        => isset( $option['step'] )        ? $option['step']        : null,
141
                        'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
142
                        'allow_blank' => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true,
143
                        'readonly'    => isset( $option['readonly'] )    ? $option['readonly']    : false,
144
                        'faux'        => isset( $option['faux'] )        ? $option['faux']        : false,
145
                        'onchange'    => !empty( $option['onchange'] )   ? $option['onchange']    : '',
146
                        'custom'      => !empty( $option['custom'] )     ? $option['custom']      : '',
147
                        'class'       =>  !empty( $option['class'] )     ? $option['class']      : '',
148
                        'cols'        => !empty( $option['cols'] ) && (int)$option['cols'] > 0 ? (int)$option['cols'] : 50,
149
                        'rows'        => !empty( $option['rows'] ) && (int)$option['rows'] > 0 ? (int)$option['rows'] : 5,
150
                    )
151
                );
152
            }
153
        }
154
    }
155
156
    // Creates our settings in the options table
157
    register_setting( 'wpinv_settings', 'wpinv_settings', 'wpinv_settings_sanitize' );
0 ignored issues
show
Bug introduced by
'wpinv_settings_sanitize' of type string is incompatible with the type array expected by parameter $args of register_setting(). ( Ignorable by Annotation )

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

157
    register_setting( 'wpinv_settings', 'wpinv_settings', /** @scrutinizer ignore-type */ 'wpinv_settings_sanitize' );
Loading history...
158
}
159
add_action( 'admin_init', 'wpinv_register_settings' );
160
161
/**
162
 * Returns an array of registered settings.
163
 */
164
function wpinv_get_registered_settings() {
165
    return apply_filters( 'wpinv_registered_settings', wpinv_get_data( 'registered-settings' ) );
166
}
167
168
function wpinv_settings_sanitize( $input = array() ) {
169
    global $wpinv_options;
170
171
    if ( empty( wp_get_raw_referer() ) ) {
172
        return $input;
173
    }
174
175
    wp_parse_str( wp_get_raw_referer(), $referrer );
0 ignored issues
show
Bug introduced by
It seems like wp_get_raw_referer() can also be of type false; however, parameter $string of wp_parse_str() 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

175
    wp_parse_str( /** @scrutinizer ignore-type */ wp_get_raw_referer(), $referrer );
Loading history...
176
177
    $settings = wpinv_get_registered_settings();
178
    $tab      = isset( $referrer['tab'] ) ? $referrer['tab'] : 'general';
179
    $section  = isset( $referrer['section'] ) ? $referrer['section'] : 'main';
180
181
    $input = $input ? $input : array();
182
    $input = apply_filters( 'wpinv_settings_tab_' . $tab . '_sanitize', $input );
183
    $input = apply_filters( 'wpinv_settings_' . $tab . '-' . $section . '_sanitize', $input );
184
185
    // Loop through each setting being saved and pass it through a sanitization filter
186
    foreach ( $input as $key => $value ) {
187
188
        // Get the setting type (checkbox, select, etc)
189
        $type = isset( $settings[ $tab ][ $key ]['type'] ) ? $settings[ $tab ][ $key ]['type'] : false;
190
191
        if ( ! $type ) {
192
            $type = isset( $settings[ $tab ][ $section ][ $key ]['type'] ) ? $settings[ $tab ][ $section ][ $key ]['type'] : false;
193
        }
194
195
        if ( $type ) {
196
            // Field type specific filter
197
            $input[$key] = apply_filters( 'wpinv_settings_sanitize_' . $type, $value, $key );
198
        }
199
200
        // General filter
201
        $input[ $key ] = apply_filters( 'wpinv_settings_sanitize', $input[ $key ], $key );
202
    }
203
204
    // Loop through the whitelist and unset any that are empty for the tab being saved
205
    $main_settings    = $section == 'main' ? $settings[ $tab ] : array(); // Check for extensions that aren't using new sections
206
    $section_settings = ! empty( $settings[ $tab ][ $section ] ) ? $settings[ $tab ][ $section ] : array();
207
208
    $found_settings = array_merge( $main_settings, $section_settings );
209
210
    if ( ! empty( $found_settings ) ) {
211
        foreach ( $found_settings as $key => $value ) {
212
213
            // settings used to have numeric keys, now they have keys that match the option ID. This ensures both methods work
214
            if ( is_numeric( $key ) ) {
215
                $key = $value['id'];
216
            }
217
218
            if ( empty( $input[ $key ] ) ) {
219
                unset( $wpinv_options[ $key ] );
220
            }
221
        }
222
    }
223
224
    // Merge our new settings with the existing
225
    $output = array_merge( $wpinv_options, $input );
226
227
    add_settings_error( 'wpinv-notices', '', __( 'Settings updated.', 'invoicing' ), 'updated' );
228
229
    return $output;
230
}
231
232
function wpinv_settings_sanitize_misc_accounting( $input ) {
233
    global $wpi_session;
234
235
    if ( ! wpinv_current_user_can_manage_invoicing() ) {
236
        return $input;
237
    }
238
239
    if( ! empty( $input['enable_sequential'] ) && !wpinv_get_option( 'enable_sequential' ) ) {
240
        // Shows an admin notice about upgrading previous order numbers
241
        $wpi_session->set( 'upgrade_sequential', '1' );
242
    }
243
244
    return $input;
245
}
246
add_filter( 'wpinv_settings_misc-accounting_sanitize', 'wpinv_settings_sanitize_misc_accounting' );
247
248
function wpinv_settings_sanitize_tax_rates( $input ) {
249
    if( ! wpinv_current_user_can_manage_invoicing() ) {
250
        return $input;
251
    }
252
253
    $new_rates = !empty( $_POST['tax_rates'] ) ? array_values( $_POST['tax_rates'] ) : array();
254
255
    $tax_rates = array();
256
257
    if ( !empty( $new_rates ) ) {
258
        foreach ( $new_rates as $rate ) {
259
            if ( isset( $rate['country'] ) && empty( $rate['country'] ) && empty( $rate['state'] ) ) {
260
                continue;
261
            }
262
            
263
            $rate['rate'] = wpinv_sanitize_amount( $rate['rate'], 4 );
264
            
265
            $tax_rates[] = $rate;
266
        }
267
    }
268
269
    update_option( 'wpinv_tax_rates', $tax_rates );
270
271
    return $input;
272
}
273
add_filter( 'wpinv_settings_taxes-rates_sanitize', 'wpinv_settings_sanitize_tax_rates' );
274
275
function wpinv_sanitize_text_field( $input ) {
276
    return trim( $input );
277
}
278
add_filter( 'wpinv_settings_sanitize_text', 'wpinv_sanitize_text_field' );
279
280
/**
281
 * Sanitizes checkout fields
282
 */
283
function wpinv_sanitize_checkout_fields_field( $input ) {
284
285
    // Checkout fields are json encoded.
286
    if ( is_string( $input ) ) {
287
        $input = json_decode( $input, true );
288
    }
289
290
    // Ensure that we have an array.
291
    if ( ! is_array( $input ) ) {
292
        $input = wpinv_get_default_checkout_fields();
293
    }
294
295
    return $input;
296
}
297
add_filter( 'wpinv_settings_sanitize_checkout_fields', 'wpinv_sanitize_checkout_fields_field' );
298
299
function wpinv_get_settings_tabs() {
300
    $tabs             = array();
301
    $tabs['general']  = __( 'General', 'invoicing' );
302
    $tabs['gateways'] = __( 'Payment Gateways', 'invoicing' );
303
    $tabs['checkout'] = __( 'Checkout', 'invoicing' );
304
    $tabs['taxes']    = __( 'Taxes', 'invoicing' );
305
    $tabs['emails']   = __( 'Emails', 'invoicing' );
306
    $tabs['privacy']  = __( 'Privacy', 'invoicing' );
307
    $tabs['misc']     = __( 'Misc', 'invoicing' );
308
    $tabs['tools']    = __( 'Tools', 'invoicing' );
309
310
    return apply_filters( 'wpinv_settings_tabs', $tabs );
311
}
312
313
function wpinv_get_settings_tab_sections( $tab = false ) {
314
    $tabs     = false;
315
    $sections = wpinv_get_registered_settings_sections();
316
317
    if( $tab && ! empty( $sections[ $tab ] ) ) {
318
        $tabs = $sections[ $tab ];
319
    } else if ( $tab ) {
320
        $tabs = false;
321
    }
322
323
    return $tabs;
324
}
325
326
function wpinv_get_registered_settings_sections() {
327
    static $sections = false;
328
329
    if ( false !== $sections ) {
330
        return $sections;
331
    }
332
333
    $sections = array(
334
        'general' => apply_filters( 'wpinv_settings_sections_general', array(
335
            'main' => __( 'General Settings', 'invoicing' ),
336
            'currency_section' => __( 'Currency Settings', 'invoicing' ),
337
            'labels' => __( 'Label Texts', 'invoicing' ),
338
        ) ),
339
        'gateways' => apply_filters( 'wpinv_settings_sections_gateways', array(
340
            'main' => __( 'Gateway Settings', 'invoicing' ),
341
        ) ),
342
        'checkout' => apply_filters( 'wpinv_settings_sections_checkout', array(
343
            'main' => __( 'Checkout Settings', 'invoicing' ),
344
        ) ),
345
        'taxes' => apply_filters( 'wpinv_settings_sections_taxes', array(
346
            'main' => __( 'Tax Settings', 'invoicing' ),
347
            'rates' => __( 'Tax Rates', 'invoicing' ),
348
        ) ),
349
        'emails' => apply_filters( 'wpinv_settings_sections_emails', array(
350
            'main' => __( 'Email Settings', 'invoicing' ),
351
        ) ),
352
        'privacy' => apply_filters( 'wpinv_settings_sections_privacy', array(
353
            'main' => __( 'Privacy policy', 'invoicing' ),
354
        ) ),
355
        'misc' => apply_filters( 'wpinv_settings_sections_misc', array(
356
            'main' => __( 'Miscellaneous', 'invoicing' ),
357
            'fields' => __( 'Fields Settings', 'invoicing' ),
358
            'custom-css' => __( 'Custom CSS', 'invoicing' ),
359
        ) ),
360
        'tools' => apply_filters( 'wpinv_settings_sections_tools', array(
361
            'main' => __( 'Diagnostic Tools', 'invoicing' ),
362
        ) ),
363
    );
364
365
    $sections = apply_filters( 'wpinv_settings_sections', $sections );
366
367
    return $sections;
368
}
369
370
function wpinv_get_pages( $with_slug = false, $default_label = NULL ) {
371
	$pages_options = array();
372
373
	if( $default_label !== NULL && $default_label !== false ) {
374
		$pages_options = array( '' => $default_label ); // Blank option
375
	}
376
377
	$pages = get_pages();
378
	if ( $pages ) {
379
		foreach ( $pages as $page ) {
380
			$title = $with_slug ? $page->post_title . ' (' . $page->post_name . ')' : $page->post_title;
381
            $pages_options[ $page->ID ] = $title;
382
		}
383
	}
384
385
	return $pages_options;
386
}
387
388
function wpinv_header_callback( $args ) {
389
	if ( !empty( $args['desc'] ) ) {
390
        echo $args['desc'];
391
    }
392
}
393
394
function wpinv_hidden_callback( $args ) {
395
	global $wpinv_options;
396
397
	if ( isset( $args['set_value'] ) ) {
398
		$value = $args['set_value'];
399
	} elseif ( isset( $wpinv_options[ $args['id'] ] ) ) {
400
		$value = $wpinv_options[ $args['id'] ];
401
	} else {
402
		$value = isset( $args['std'] ) ? $args['std'] : '';
403
	}
404
405
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
406
		$args['readonly'] = true;
407
		$value = isset( $args['std'] ) ? $args['std'] : '';
408
		$name  = '';
409
	} else {
410
		$name = 'name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"';
411
	}
412
413
	$html = '<input type="hidden" id="wpinv_settings[' . wpinv_sanitize_key( $args['id'] ) . ']" ' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '" />';
414
    
415
	echo $html;
416
}
417
418
function wpinv_checkbox_callback( $args ) {
419
	global $wpinv_options;
420
    
421
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
422
423
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
424
		$name = '';
425
	} else {
426
		$name = 'name="wpinv_settings[' . $sanitize_id . ']"';
427
	}
428
429
	$checked = isset( $wpinv_options[ $args['id'] ] ) ? checked( 1, $wpinv_options[ $args['id'] ], false ) : '';
430
	$html = '<input type="checkbox" id="wpinv_settings[' . $sanitize_id . ']"' . $name . ' value="1" ' . $checked . '/>';
431
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
432
433
	echo $html;
434
}
435
436
function wpinv_checkout_fields_callback( $args ) {
437
    include plugin_dir_path( __FILE__ ) . 'checkout-fields-template.php';
438
}
439
440
function wpinv_multicheck_callback( $args ) {
441
	global $wpinv_options;
442
443
	$sanitize_id = wpinv_sanitize_key( $args['id'] );
444
	$class = !empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
445
446
	if ( ! empty( $args['options'] ) ) {
447
		echo '<div class="wpi-mcheck-rows wpi-mcheck-' . $sanitize_id . $class . '">';
448
        foreach( $args['options'] as $key => $option ):
449
			$sanitize_key = wpinv_sanitize_key( $key );
450
			if ( isset( $wpinv_options[$args['id']][$sanitize_key] ) ) { 
451
				$enabled = $sanitize_key;
452
			} else { 
453
				$enabled = NULL; 
454
			}
455
			echo '<div class="wpi-mcheck-row"><input name="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" id="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" type="checkbox" value="' . esc_attr( $sanitize_key ) . '" ' . checked( $sanitize_key, $enabled, false ) . '/>&nbsp;';
456
			echo '<label for="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']">' . wp_kses_post( $option ) . '</label></div>';
457
		endforeach;
458
		echo '</div>';
459
		echo '<p class="description">' . $args['desc'] . '</p>';
460
	}
461
}
462
463
function wpinv_payment_icons_callback( $args ) {
464
	global $wpinv_options;
465
    
466
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
467
468
	if ( ! empty( $args['options'] ) ) {
469
		foreach( $args['options'] as $key => $option ) {
470
            $sanitize_key = wpinv_sanitize_key( $key );
471
            
472
			if( isset( $wpinv_options[$args['id']][$key] ) ) {
473
				$enabled = $option;
474
			} else {
475
				$enabled = NULL;
476
			}
477
478
			echo '<label for="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" style="margin-right:10px;line-height:16px;height:16px;display:inline-block;">';
479
480
				echo '<input name="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" id="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" type="checkbox" value="' . esc_attr( $option ) . '" ' . checked( $option, $enabled, false ) . '/>&nbsp;';
481
482
				if ( wpinv_string_is_image_url( $key ) ) {
483
					echo '<img class="payment-icon" src="' . esc_url( $key ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
484
				} else {
485
					$card = strtolower( str_replace( ' ', '', $option ) );
486
487
					if ( has_filter( 'wpinv_accepted_payment_' . $card . '_image' ) ) {
488
						$image = apply_filters( 'wpinv_accepted_payment_' . $card . '_image', '' );
489
					} else {
490
						$image       = wpinv_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', false );
491
						$content_dir = WP_CONTENT_DIR;
492
493
						if ( function_exists( 'wp_normalize_path' ) ) {
494
							// Replaces backslashes with forward slashes for Windows systems
495
							$image = wp_normalize_path( $image );
496
							$content_dir = wp_normalize_path( $content_dir );
497
						}
498
499
						$image = str_replace( $content_dir, content_url(), $image );
500
					}
501
502
					echo '<img class="payment-icon" src="' . esc_url( $image ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
503
				}
504
			echo $option . '</label>';
505
		}
506
		echo '<p class="description" style="margin-top:16px;">' . wp_kses_post( $args['desc'] ) . '</p>';
507
	}
508
}
509
510
function wpinv_radio_callback( $args ) {
511
	global $wpinv_options;
512
    
513
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
514
    
515
    foreach ( $args['options'] as $key => $option ) :
516
		$sanitize_key = wpinv_sanitize_key( $key );
517
        
518
        $checked = false;
519
520
		if ( isset( $wpinv_options[ $args['id'] ] ) && $wpinv_options[ $args['id'] ] == $key )
521
			$checked = true;
522
		elseif( isset( $args['std'] ) && $args['std'] == $key && ! isset( $wpinv_options[ $args['id'] ] ) )
523
			$checked = true;
524
525
		echo '<input name="wpinv_settings[' . $sanitize_id . ']" id="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" type="radio" value="' . $sanitize_key . '" ' . checked(true, $checked, false) . '/>&nbsp;';
526
		echo '<label for="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']">' . esc_html( $option ) . '</label><br/>';
527
	endforeach;
528
529
	echo '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
530
}
531
532
function wpinv_gateways_callback( $args ) {
533
	global $wpinv_options;
534
    
535
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
536
537
	foreach ( $args['options'] as $key => $option ) :
538
		$sanitize_key = wpinv_sanitize_key( $key );
539
        
540
        if ( isset( $wpinv_options['gateways'][ $key ] ) )
541
			$enabled = '1';
542
		else
543
			$enabled = null;
544
545
		echo '<input name="wpinv_settings[' . esc_attr( $args['id'] ) . '][' . $sanitize_key . ']" id="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']" type="checkbox" value="1" ' . checked('1', $enabled, false) . '/>&nbsp;';
546
		echo '<label for="wpinv_settings[' . $sanitize_id . '][' . $sanitize_key . ']">' . esc_html( $option['admin_label'] ) . '</label><br/>';
547
	endforeach;
548
}
549
550
function wpinv_gateway_select_callback($args) {
551
	global $wpinv_options;
552
    
553
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
554
    $class = !empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
555
556
	echo '<select name="wpinv_settings[' . $sanitize_id . ']"" id="wpinv_settings[' . $sanitize_id . ']" class="'.$class.'" >';
557
558
	foreach ( $args['options'] as $key => $option ) :
559
		if ( isset( $args['selected'] ) && $args['selected'] !== null && $args['selected'] !== false ) {
560
            $selected = selected( $key, $args['selected'], false );
561
        } else {
562
            $selected = isset( $wpinv_options[ $args['id'] ] ) ? selected( $key, $wpinv_options[$args['id']], false ) : '';
563
        }
564
		echo '<option value="' . wpinv_sanitize_key( $key ) . '"' . $selected . '>' . esc_html( $option['admin_label'] ) . '</option>';
565
	endforeach;
566
567
	echo '</select>';
568
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
569
}
570
571
function wpinv_text_callback( $args ) {
572
	global $wpinv_options;
573
    
574
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
575
576
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
577
		$value = $wpinv_options[ $args['id'] ];
578
	} else {
579
		$value = isset( $args['std'] ) ? $args['std'] : '';
580
	}
581
582
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
583
		$args['readonly'] = true;
584
		$value = isset( $args['std'] ) ? $args['std'] : '';
585
		$name  = '';
586
	} else {
587
		$name = 'name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"';
588
	}
589
	$class = !empty( $args['class'] ) ? sanitize_html_class( $args['class'] ) : '';
590
591
	$readonly = $args['readonly'] === true ? ' readonly="readonly"' : '';
592
	$size     = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
593
	$html     = '<input type="text" class="' . sanitize_html_class( $size ) . '-text ' . $class . '" id="wpinv_settings[' . $sanitize_id . ']" ' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"' . $readonly . '/>';
594
	$html    .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
595
596
	echo $html;
597
}
598
599
function wpinv_number_callback( $args ) {
600
	global $wpinv_options;
601
    
602
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
603
604
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
605
		$value = $wpinv_options[ $args['id'] ];
606
	} else {
607
		$value = isset( $args['std'] ) ? $args['std'] : '';
608
	}
609
610
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
611
		$args['readonly'] = true;
612
		$value = isset( $args['std'] ) ? $args['std'] : '';
613
		$name  = '';
614
	} else {
615
		$name = 'name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"';
616
	}
617
618
	$max  = isset( $args['max'] ) ? $args['max'] : 999999;
619
	$min  = isset( $args['min'] ) ? $args['min'] : 0;
620
	$step = isset( $args['step'] ) ? $args['step'] : 1;
621
	$class = !empty( $args['class'] ) ? sanitize_html_class( $args['class'] ) : '';
622
623
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
624
	$html = '<input type="number" step="' . esc_attr( $step ) . '" max="' . esc_attr( $max ) . '" min="' . esc_attr( $min ) . '" class="' . sanitize_html_class( $size ) . '-text ' . $class . '" id="wpinv_settings[' . $sanitize_id . ']" ' . $name . ' value="' . esc_attr( stripslashes( $value ) ) . '"/>';
625
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
626
627
	echo $html;
628
}
629
630
function wpinv_textarea_callback( $args ) {
631
	global $wpinv_options;
632
    
633
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
634
635
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
636
		$value = $wpinv_options[ $args['id'] ];
637
	} else {
638
		$value = isset( $args['std'] ) ? $args['std'] : '';
639
	}
640
    
641
    $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
642
    $class = ( isset( $args['class'] ) && ! is_null( $args['class'] ) ) ? $args['class'] : 'large-text';
643
644
	$html = '<textarea class="' . sanitize_html_class( $class ) . ' txtarea-' . sanitize_html_class( $size ) . ' wpi-' . esc_attr( sanitize_html_class( $sanitize_id ) ) . ' " cols="' . $args['cols'] . '" rows="' . $args['rows'] . '" id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
645
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
646
647
	echo $html;
648
}
649
650
function wpinv_password_callback( $args ) {
651
	global $wpinv_options;
652
    
653
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
654
655
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
656
		$value = $wpinv_options[ $args['id'] ];
657
	} else {
658
		$value = isset( $args['std'] ) ? $args['std'] : '';
659
	}
660
661
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
662
	$html = '<input type="password" class="' . sanitize_html_class( $size ) . '-text" id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( $value ) . '"/>';
663
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
664
665
	echo $html;
666
}
667
668
function wpinv_missing_callback($args) {
669
	printf(
670
		__( 'The callback function used for the %s setting is missing.', 'invoicing' ),
671
		'<strong>' . $args['id'] . '</strong>'
672
	);
673
}
674
675
function wpinv_select_callback($args) {
676
	global $wpinv_options;
677
    
678
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
679
680
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
681
		$value = $wpinv_options[ $args['id'] ];
682
	} else {
683
		$value = isset( $args['std'] ) ? $args['std'] : '';
684
	}
685
    
686
    if ( isset( $args['selected'] ) && $args['selected'] !== null && $args['selected'] !== false ) {
687
        $value = $args['selected'];
688
    }
689
690
	if ( isset( $args['placeholder'] ) ) {
691
		$placeholder = $args['placeholder'];
692
	} else {
693
		$placeholder = '';
694
	}
695
    
696
    if( !empty( $args['onchange'] ) ) {
697
        $onchange = ' onchange="' . esc_attr( $args['onchange'] ) . '"';
698
    } else {
699
        $onchange = '';
700
    }
701
702
    $class = !empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
703
704
	$html = '<select id="wpinv_settings[' . $sanitize_id . ']" class="'.$class.'"  name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" data-placeholder="' . esc_html( $placeholder ) . '"' . $onchange . ' />';
705
706
	foreach ( $args['options'] as $option => $name ) {
707
		$selected = selected( $option, $value, false );
708
		$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>';
709
	}
710
711
	$html .= '</select>';
712
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
713
714
	echo $html;
715
}
716
717
function wpinv_color_select_callback( $args ) {
718
	global $wpinv_options;
719
    
720
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
721
722
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
723
		$value = $wpinv_options[ $args['id'] ];
724
	} else {
725
		$value = isset( $args['std'] ) ? $args['std'] : '';
726
	}
727
728
	$html = '<select id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"/>';
729
730
	foreach ( $args['options'] as $option => $color ) {
731
		$selected = selected( $option, $value, false );
732
		$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $color['label'] ) . '</option>';
733
	}
734
735
	$html .= '</select>';
736
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
737
738
	echo $html;
739
}
740
741
function wpinv_rich_editor_callback( $args ) {
742
	global $wpinv_options, $wp_version;
743
    
744
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
745
746
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
747
		$value = $wpinv_options[ $args['id'] ];
748
749
		if( empty( $args['allow_blank'] ) && empty( $value ) ) {
750
			$value = isset( $args['std'] ) ? $args['std'] : '';
751
		}
752
	} else {
753
		$value = isset( $args['std'] ) ? $args['std'] : '';
754
	}
755
756
	$rows = isset( $args['size'] ) ? $args['size'] : 20;
757
758
	if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) {
759
		ob_start();
760
		wp_editor( stripslashes( $value ), 'wpinv_settings_' . esc_attr( $args['id'] ), array( 'textarea_name' => 'wpinv_settings[' . esc_attr( $args['id'] ) . ']', 'textarea_rows' => absint( $rows ), 'media_buttons' => false ) );
761
		$html = ob_get_clean();
762
	} else {
763
		$html = '<textarea class="large-text" rows="10" id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" class="wpi-' . esc_attr( sanitize_html_class( $args['id'] ) ) . '">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
764
	}
765
766
	$html .= '<br/><label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
767
768
	echo $html;
769
}
770
771
function wpinv_upload_callback( $args ) {
772
	global $wpinv_options;
773
    
774
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
775
776
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
777
		$value = $wpinv_options[$args['id']];
778
	} else {
779
		$value = isset($args['std']) ? $args['std'] : '';
780
	}
781
782
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
783
	$html = '<input type="text" class="' . sanitize_html_class( $size ) . '-text" id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( stripslashes( $value ) ) . '"/>';
784
	$html .= '<span>&nbsp;<input type="button" class="wpinv_settings_upload_button button-secondary" value="' . __( 'Upload File', 'invoicing' ) . '"/></span>';
785
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
786
787
	echo $html;
788
}
789
790
function wpinv_color_callback( $args ) {
791
	global $wpinv_options;
792
    
793
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
794
795
	if ( isset( $wpinv_options[ $args['id'] ] ) ) {
796
		$value = $wpinv_options[ $args['id'] ];
797
	} else {
798
		$value = isset( $args['std'] ) ? $args['std'] : '';
799
	}
800
801
	$default = isset( $args['std'] ) ? $args['std'] : '';
802
803
	$html = '<input type="text" class="wpinv-color-picker" id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( $value ) . '" data-default-color="' . esc_attr( $default ) . '" />';
804
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
805
806
	echo $html;
807
}
808
809
function wpinv_country_states_callback($args) {
810
	global $wpinv_options;
811
    
812
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
813
814
	if ( isset( $args['placeholder'] ) ) {
815
		$placeholder = $args['placeholder'];
816
	} else {
817
		$placeholder = '';
818
	}
819
820
	$states = wpinv_get_country_states();
821
822
	$class = empty( $states ) ? ' class="wpinv-no-states"' : ' class="wpi_select2"';
823
	$html = '<select id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"' . $class . 'data-placeholder="' . esc_html( $placeholder ) . '"/>';
824
825
	foreach ( $states as $option => $name ) {
826
		$selected = isset( $wpinv_options[ $args['id'] ] ) ? selected( $option, $wpinv_options[$args['id']], false ) : '';
827
		$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>';
828
	}
829
830
	$html .= '</select>';
831
	$html .= '<label for="wpinv_settings[' . $sanitize_id . ']"> '  . wp_kses_post( $args['desc'] ) . '</label>';
832
833
	echo $html;
834
}
835
836
function wpinv_tax_rates_callback($args) {
837
	global $wpinv_options;
838
	$rates = wpinv_get_tax_rates();
839
	ob_start(); ?>
840
    </td><tr>
841
    <td colspan="2" class="wpinv_tax_tdbox">
842
	<p><?php echo $args['desc']; ?></p>
843
	<table id="wpinv_tax_rates" class="wp-list-table widefat fixed posts">
844
		<thead>
845
			<tr>
846
				<th scope="col" class="wpinv_tax_country"><?php _e( 'Country', 'invoicing' ); ?></th>
847
				<th scope="col" class="wpinv_tax_state"><?php _e( 'State / Province', 'invoicing' ); ?></th>
848
                <th scope="col" class="wpinv_tax_global" title="<?php esc_attr_e( 'Apply rate to whole country, regardless of state / province', 'invoicing' ); ?>"><?php _e( 'Country Wide', 'invoicing' ); ?></th>
849
                <th scope="col" class="wpinv_tax_rate"><?php _e( 'Rate %', 'invoicing' ); ?></th> 
850
                <th scope="col" class="wpinv_tax_name"><?php _e( 'Tax Name', 'invoicing' ); ?></th>
851
				<th scope="col" class="wpinv_tax_action"><?php _e( 'Remove', 'invoicing' ); ?></th>
852
			</tr>
853
		</thead>
854
        <tbody>
855
		<?php if( !empty( $rates ) ) : ?>
856
			<?php foreach( $rates as $key => $rate ) : ?>
857
            <?php 
858
            $sanitized_key = wpinv_sanitize_key( $key );
859
            ?>
860
			<tr>
861
				<td class="wpinv_tax_country">
862
					<?php
863
					echo wpinv_html_select( array(
864
						'options'          => wpinv_get_country_list( true ),
865
						'name'             => 'tax_rates[' . $sanitized_key . '][country]',
866
                        'id'               => 'tax_rates[' . $sanitized_key . '][country]',
867
						'selected'         => $rate['country'],
868
						'show_option_all'  => false,
869
						'show_option_none' => false,
870
						'class'            => 'wpinv-tax-country wpi_select2',
871
						'placeholder'      => __( 'Choose a country', 'invoicing' )
872
					) );
873
					?>
874
				</td>
875
				<td class="wpinv_tax_state">
876
					<?php
877
					$states = wpinv_get_country_states( $rate['country'] );
878
					if( !empty( $states ) ) {
879
						echo wpinv_html_select( array(
880
							'options'          => array_merge( array( '' => '' ), $states ),
881
							'name'             => 'tax_rates[' . $sanitized_key . '][state]',
882
                            'id'               => 'tax_rates[' . $sanitized_key . '][state]',
883
							'selected'         => $rate['state'],
884
							'show_option_all'  => false,
885
							'show_option_none' => false,
886
                            'class'            => 'wpi_select2',
887
							'placeholder'      => __( 'Choose a state', 'invoicing' )
888
						) );
889
					} else {
890
						echo wpinv_html_text( array(
891
							'name'  => 'tax_rates[' . $sanitized_key . '][state]', $rate['state'],
892
							'value' => ! empty( $rate['state'] ) ? $rate['state'] : '',
893
                            'id'    => 'tax_rates[' . $sanitized_key . '][state]',
894
						) );
895
					}
896
					?>
897
				</td>
898
				<td class="wpinv_tax_global">
899
					<input type="checkbox" name="tax_rates[<?php echo $sanitized_key; ?>][global]" id="tax_rates[<?php echo $sanitized_key; ?>][global]" value="1"<?php checked( true, ! empty( $rate['global'] ) ); ?>/>
900
					<label for="tax_rates[<?php echo $sanitized_key; ?>][global]"><?php _e( 'Apply to whole country', 'invoicing' ); ?></label>
901
				</td>
902
				<td class="wpinv_tax_rate"><input type="number" class="small-text" step="any" min="0" max="99" name="tax_rates[<?php echo $sanitized_key; ?>][rate]" value="<?php echo esc_html( $rate['rate'] ); ?>"/></td>
903
                <td class="wpinv_tax_name"><input type="text" class="regular-text" name="tax_rates[<?php echo $sanitized_key; ?>][name]" value="<?php echo esc_html( $rate['name'] ); ?>"/></td>
904
				<td class="wpinv_tax_action"><span class="wpinv_remove_tax_rate button-secondary"><?php _e( 'Remove Rate', 'invoicing' ); ?></span></td>
905
			</tr>
906
			<?php endforeach; ?>
907
		<?php else : ?>
908
			<tr>
909
				<td class="wpinv_tax_country">
910
					<?php
911
					echo wpinv_html_select( array(
912
						'options'          => wpinv_get_country_list( true ),
913
						'name'             => 'tax_rates[0][country]',
914
						'show_option_all'  => false,
915
						'show_option_none' => false,
916
						'class'            => 'wpinv-tax-country wpi_select2',
917
						'placeholder'      => __( 'Choose a country', 'invoicing' )
918
					) ); ?>
919
				</td>
920
				<td class="wpinv_tax_state">
921
					<?php echo wpinv_html_text( array(
922
						'name' => 'tax_rates[0][state]'
923
					) ); ?>
924
				</td>
925
				<td class="wpinv_tax_global">
926
					<input type="checkbox" name="tax_rates[0][global]" id="tax_rates[0][global]" value="1"/>
927
					<label for="tax_rates[0][global]"><?php _e( 'Apply to whole country', 'invoicing' ); ?></label>
928
				</td>
929
				<td class="wpinv_tax_rate"><input type="number" class="small-text" step="any" min="0" max="99" name="tax_rates[0][rate]" placeholder="<?php echo (float)wpinv_get_option( 'tax_rate', 0 ) ;?>" value="<?php echo (float)wpinv_get_option( 'tax_rate', 0 ) ;?>"/></td>
930
                <td class="wpinv_tax_name"><input type="text" class="regular-text" name="tax_rates[0][name]" /></td>
931
				<td><span class="wpinv_remove_tax_rate button-secondary"><?php _e( 'Remove Rate', 'invoicing' ); ?></span></td>
932
			</tr>
933
		<?php endif; ?>
934
        </tbody>
935
        <tfoot><tr><td colspan="5"></td><td class="wpinv_tax_action"><span class="button-secondary" id="wpinv_add_tax_rate"><?php _e( 'Add Tax Rate', 'invoicing' ); ?></span></td></tr></tfoot>
936
	</table>
937
	<?php
938
	echo ob_get_clean();
939
}
940
941
function wpinv_tools_callback($args) {
942
    global $wpinv_options;
943
    ob_start(); ?>
944
    </td><tr>
945
    <td colspan="2" class="wpinv_tools_tdbox">
946
    <?php if ( $args['desc'] ) { ?><p><?php echo $args['desc']; ?></p><?php } ?>
947
    <?php do_action( 'wpinv_tools_before' ); ?>
948
    <table id="wpinv_tools_table" class="wp-list-table widefat fixed posts">
949
        <thead>
950
            <tr>
951
                <th scope="col" class="wpinv-th-tool"><?php _e( 'Tool', 'invoicing' ); ?></th>
952
                <th scope="col" class="wpinv-th-desc"><?php _e( 'Description', 'invoicing' ); ?></th>
953
                <th scope="col" class="wpinv-th-action"><?php _e( 'Action', 'invoicing' ); ?></th>
954
            </tr>
955
        </thead>
956
            <?php do_action( 'wpinv_tools_row' ); ?>
957
        <tbody>
958
        </tbody>
959
    </table>
960
    <?php do_action( 'wpinv_tools_after' ); ?>
961
    <?php
962
    echo ob_get_clean();
963
}
964
965
function wpinv_descriptive_text_callback( $args ) {
966
	echo wp_kses_post( $args['desc'] );
967
}
968
969
function wpinv_hook_callback( $args ) {
970
	do_action( 'wpinv_' . $args['id'], $args );
971
}
972
973
function wpinv_set_settings_cap() {
974
	return wpinv_get_capability();
975
}
976
add_filter( 'option_page_capability_wpinv_settings', 'wpinv_set_settings_cap' );
977
978
function wpinv_settings_sanitize_input( $value, $key ) {
979
    if ( $key == 'tax_rate' || $key == 'eu_fallback_rate' ) {
980
        $value = wpinv_sanitize_amount( $value, 4 );
981
        $value = $value >= 100 ? 99 : $value;
982
    }
983
        
984
    return $value;
985
}
986
add_filter( 'wpinv_settings_sanitize', 'wpinv_settings_sanitize_input', 10, 2 );
987
988
function wpinv_on_update_settings( $old_value, $value, $option ) {
989
    $old = !empty( $old_value['remove_data_on_unistall'] ) ? 1 : '';
990
    $new = !empty( $value['remove_data_on_unistall'] ) ? 1 : '';
991
    
992
    if ( $old != $new ) {
993
        update_option( 'wpinv_remove_data_on_invoice_unistall', $new );
994
    }
995
}
996
add_action( 'update_option_wpinv_settings', 'wpinv_on_update_settings', 10, 3 );
997
add_action( 'wpinv_settings_tab_bottom_emails_new_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
998
add_action( 'wpinv_settings_tab_bottom_emails_cancelled_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
999
add_action( 'wpinv_settings_tab_bottom_emails_failed_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1000
add_action( 'wpinv_settings_tab_bottom_emails_onhold_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1001
add_action( 'wpinv_settings_tab_bottom_emails_processing_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1002
add_action( 'wpinv_settings_tab_bottom_emails_completed_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1003
add_action( 'wpinv_settings_tab_bottom_emails_refunded_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1004
add_action( 'wpinv_settings_tab_bottom_emails_user_invoice', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1005
add_action( 'wpinv_settings_tab_bottom_emails_user_note', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1006
add_action( 'wpinv_settings_tab_bottom_emails_overdue', 'wpinv_settings_tab_bottom_emails', 10, 2 );
1007
1008
function wpinv_settings_tab_bottom_emails( $active_tab, $section ) {
1009
    ?>
1010
    <div class="wpinv-email-wc-row ">
1011
        <div class="wpinv-email-wc-td">
1012
            <h3 class="wpinv-email-wc-title"><?php echo apply_filters( 'wpinv_settings_email_wildcards_title', __( 'Wildcards For Emails', 'invoicing' ) ); ?></h3>
1013
            <p class="wpinv-email-wc-description">
1014
                <?php
1015
                $description = __( 'The following wildcards can be used in email subjects, heading and content:<br>
1016
                    <strong>{site_title} :</strong> Site Title<br>
1017
                    <strong>{name} :</strong> Customer\'s full name<br>
1018
                    <strong>{first_name} :</strong> Customer\'s first name<br>
1019
                    <strong>{last_name} :</strong> Customer\'s last name<br>
1020
                    <strong>{email} :</strong> Customer\'s email address<br>
1021
                    <strong>{invoice_number} :</strong> The invoice number<br>
1022
                    <strong>{invoice_total} :</strong> The invoice total<br>
1023
                    <strong>{invoice_link} :</strong> The invoice link<br>
1024
                    <strong>{invoice_pay_link} :</strong> The payment link<br>
1025
                    <strong>{invoice_date} :</strong> The date the invoice was created<br>
1026
                    <strong>{invoice_due_date} :</strong> The date the invoice is due<br>
1027
                    <strong>{date} :</strong> Today\'s date.<br>
1028
                    <strong>{is_was} :</strong> If due date of invoice is past, displays "was" otherwise displays "is"<br>
1029
                    <strong>{invoice_label} :</strong> Invoices/quotes singular name. Ex: Invoice/Quote<br>', 'invoicing' );
1030
                echo apply_filters('wpinv_settings_email_wildcards_description', $description, $active_tab, $section);
1031
                ?>
1032
            </p>
1033
        </div>
1034
    </div>
1035
    <?php
1036
}