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

wpinv_settings_attrs_helper()   B

Complexity

Conditions 9
Paths 128

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 21
nc 128
nop 1
dl 0
loc 31
rs 7.8222
c 1
b 0
f 0
1
<?php
2
/**
3
 * Contains settings related functions
4
 *
5
 * @package Invoicing
6
 * @since   1.0.0
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Retrieves all default settings.
13
 *
14
 * @return array
15
 */
16
function wpinv_get_settings() {
17
    $defaults = array();
18
19
    foreach ( array_values( wpinv_get_registered_settings() ) as $tab_settings ) {
20
21
        foreach ( array_values( $tab_settings ) as $section_settings ) {
22
23
            foreach ( $section_settings as $key => $setting ) {
24
                if ( isset( $setting['std'] ) ) {
25
                    $defaults[ $key ] = $setting['std'];
26
                }
27
            }
28
}
29
}
30
31
    return $defaults;
32
33
}
34
35
/**
36
 * Retrieves all settings.
37
 *
38
 * @return array
39
 */
40
function wpinv_get_options() {
41
    global $wpinv_options;
42
43
    // Try fetching the saved options.
44
    if ( empty( $wpinv_options ) ) {
45
        $wpinv_options = get_option( 'wpinv_settings' );
46
    }
47
48
    // If that fails, don't fetch the default settings to prevent a loop.
49
    if ( ! is_array( $wpinv_options ) ) {
50
        $wpinv_options = array();
51
    }
52
53
    return $wpinv_options;
54
}
55
56
/**
57
 * Retrieves a single setting.
58
 *
59
 * @param string $key the setting key.
60
 * @param mixed $default The default value to use if the setting has not been set.
61
 * @return mixed
62
 */
63
function wpinv_get_option( $key = '', $default = false ) {
64
65
    $options = wpinv_get_options();
66
    $value   = isset( $options[ $key ] ) ? $options[ $key ] : $default;
67
    $value   = apply_filters( 'wpinv_get_option', $value, $key, $default );
68
69
    return apply_filters( 'wpinv_get_option_' . $key, $value, $key, $default );
70
}
71
72
/**
73
 * Updates all settings.
74
 *
75
 * @param array $options the new options.
76
 * @return bool
77
 */
78
function wpinv_update_options( $options ) {
79
    global $wpinv_options;
80
81
    // update the option.
82
    if ( is_array( $options ) && update_option( 'wpinv_settings', $options ) ) {
83
        $wpinv_options = $options;
84
        return true;
85
    }
86
87
    return false;
88
}
89
90
/**
91
 * Updates a single setting.
92
 *
93
 * @param string $key the setting key.
94
 * @param mixed $value The setting value.
95
 * @return bool
96
 */
97
function wpinv_update_option( $key = '', $value = false ) {
98
99
    // If no key, exit.
100
    if ( empty( $key ) ) {
101
        return false;
102
    }
103
104
    // Maybe delete the option instead.
105
    if ( is_null( $value ) ) {
106
        return wpinv_delete_option( $key );
107
    }
108
109
    // Prepare the new options.
110
    $options         = wpinv_get_options();
111
    $options[ $key ] = apply_filters( 'wpinv_update_option', $value, $key );
112
113
    // Save the new options.
114
    return wpinv_update_options( $options );
115
116
}
117
118
/**
119
 * Deletes a single setting.
120
 *
121
 * @param string $key the setting key.
122
 * @return bool
123
 */
124
function wpinv_delete_option( $key = '' ) {
125
126
    // If no key, exit
127
    if ( empty( $key ) ) {
128
        return false;
129
    }
130
131
    $options = wpinv_get_options();
132
133
    if ( isset( $options[ $key ] ) ) {
134
        unset( $options[ $key ] );
135
        return wpinv_update_options( $options );
136
    }
137
138
    return true;
139
140
}
141
142
/**
143
 * Register settings after admin inits.
144
 *
145
 */
146
function wpinv_register_settings() {
147
148
    // Loop through all tabs.
149
    foreach ( wpinv_get_registered_settings() as $tab => $sections ) {
150
151
        // In each tab, loop through sections.
152
        foreach ( $sections as $section => $settings ) {
153
154
            // Check for backwards compatibility
155
            $section_tabs = wpinv_get_settings_tab_sections( $tab );
156
            if ( ! is_array( $section_tabs ) || ! array_key_exists( $section, $section_tabs ) ) {
157
                $section = 'main';
158
                $settings = $sections;
159
            }
160
161
            // Register the setting section.
162
            add_settings_section(
163
                'wpinv_settings_' . $tab . '_' . $section,
164
                __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...
165
                '__return_false',
166
                'wpinv_settings_' . $tab . '_' . $section
167
            );
168
169
            foreach ( $settings as $option ) {
170
                if ( ! empty( $option['id'] ) ) {
171
                    wpinv_register_settings_option( $tab, $section, $option );
172
                }
173
            }
174
}
175
    }
176
177
    // Creates our settings in the options table.
178
    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

178
    register_setting( 'wpinv_settings', 'wpinv_settings', /** @scrutinizer ignore-type */ 'wpinv_settings_sanitize' );
Loading history...
179
}
180
add_action( 'admin_init', 'wpinv_register_settings' );
181
182
/**
183
 * Register a single settings option.
184
 *
185
 * @param string $tab
186
 * @param string $section
187
 * @param string $option
188
 *
189
 */
190
function wpinv_register_settings_option( $tab, $section, $option ) {
191
192
    $name       = isset( $option['name'] ) ? $option['name'] : '';
193
    $cb         = "wpinv_{$option['type']}_callback";
194
    $section    = "wpinv_settings_{$tab}_$section";
195
	$is_wizzard = is_admin() && isset( $_GET['page'] ) && 'gp-setup' == $_GET['page'];
196
197
	if ( isset( $option['desc'] ) && ( ! $is_wizzard && ! empty( $option['help-tip'] ) ) ) {
198
		$tip   = wpinv_clean( $option['desc'] );
199
		$name .= "<span class='dashicons dashicons-editor-help wpi-help-tip' title='$tip'></span>";
200
		unset( $option['desc'] );
201
	}
202
203
    // Loop through all tabs.
204
    add_settings_field(
205
        'wpinv_settings[' . $option['id'] . ']',
206
        $name,
207
        function_exists( $cb ) ? $cb : 'wpinv_missing_callback',
208
        $section,
209
        $section,
210
        array(
211
            'section'         => $section,
212
            'id'              => isset( $option['id'] ) ? $option['id'] : uniqid( 'wpinv-' ),
213
            'desc'            => isset( $option['desc'] ) ? $option['desc'] : '',
214
            'name'            => $name,
215
            'size'            => isset( $option['size'] ) ? $option['size'] : null,
216
            'options'         => isset( $option['options'] ) ? $option['options'] : '',
217
            'selected'        => isset( $option['selected'] ) ? $option['selected'] : null,
218
            'std'             => isset( $option['std'] ) ? $option['std'] : '',
219
            'min'             => isset( $option['min'] ) ? $option['min'] : 0,
220
            'max'             => isset( $option['max'] ) ? $option['max'] : 999999,
221
            'step'            => isset( $option['step'] ) ? $option['step'] : 1,
222
            'placeholder'     => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
223
            'allow_blank'     => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true,
224
            'readonly'        => isset( $option['readonly'] ) ? $option['readonly'] : false,
225
            'faux'            => isset( $option['faux'] ) ? $option['faux'] : false,
226
            'onchange'        => isset( $option['onchange'] ) ? $option['onchange'] : '',
227
            'custom'          => isset( $option['custom'] ) ? $option['custom'] : '',
228
			'default_content' => isset( $option['default_content'] ) ? $option['default_content'] : '',
229
			'class'           => isset( $option['class'] ) ? $option['class'] : '',
230
			'style'           => isset( $option['style'] ) ? $option['style'] : '',
231
            'cols'            => isset( $option['cols'] ) && (int) $option['cols'] > 0 ? (int) $option['cols'] : 50,
232
            'rows'            => isset( $option['rows'] ) && (int) $option['rows'] > 0 ? (int) $option['rows'] : 5,
233
        )
234
    );
235
236
}
237
238
/**
239
 * Returns an array of all registered settings.
240
 *
241
 * @return array
242
 */
243
function wpinv_get_registered_settings() {
244
	return array_filter( apply_filters( 'wpinv_registered_settings', wpinv_get_data( 'admin-settings' ) ) );
245
}
246
247
/**
248
 * Returns an array of all integration settings.
249
 *
250
 * @return array
251
 */
252
function getpaid_get_integration_settings() {
253
    return apply_filters( 'getpaid_integration_settings', array() );
254
}
255
256
/**
257
 * Sanitizes settings before they are saved.
258
 *
259
 * @return array
260
 */
261
function wpinv_settings_sanitize( $input = array() ) {
262
263
	$wpinv_options = wpinv_get_options();
264
	$raw_referrer  = wp_get_raw_referer();
265
266
    if ( empty( $raw_referrer ) ) {
267
		return array_merge( $wpinv_options, $input );
268
    }
269
270
    wp_parse_str( $raw_referrer, $referrer );
271
272
	if ( in_array( 'gp-setup', $referrer ) ) {
273
		return array_merge( $wpinv_options, $input );
274
	}
275
276
    $settings = wpinv_get_registered_settings();
277
    $tab      = isset( $referrer['tab'] ) ? $referrer['tab'] : 'general';
278
    $section  = isset( $referrer['section'] ) ? $referrer['section'] : 'main';
279
280
    $input = $input ? $input : array();
281
    $input = apply_filters( 'wpinv_settings_tab_' . $tab . '_sanitize', $input );
282
    $input = apply_filters( 'wpinv_settings_' . $tab . '-' . $section . '_sanitize', $input );
283
284
    // Loop through each setting being saved and pass it through a sanitization filter
285
    foreach ( $input as $key => $value ) {
286
287
        // Get the setting type (checkbox, select, etc)
288
        $type = isset( $settings[ $tab ][ $section ][ $key ]['type'] ) ? $settings[ $tab ][ $section ][ $key ]['type'] : false;
289
290
        if ( $type ) {
291
            // Field type specific filter
292
            $input[ $key ] = apply_filters( "wpinv_settings_sanitize_$type", $value, $key );
293
        }
294
295
        // General filter
296
		$input[ $key ] = apply_filters( 'wpinv_settings_sanitize', $input[ $key ], $key );
297
298
		// Key specific filter.
299
		$input[ $key ] = apply_filters( "wpinv_settings_sanitize_$key", $input[ $key ] );
300
    }
301
302
    // Loop through the whitelist and unset any that are empty for the tab being saved
303
    $main_settings    = isset( $settings[ $tab ] ) ? $settings[ $tab ] : array(); // Check for extensions that aren't using new sections
304
    $section_settings = ! empty( $settings[ $tab ][ $section ] ) ? $settings[ $tab ][ $section ] : array();
305
306
    $found_settings   = array_merge( $main_settings, $section_settings );
307
308
    if ( ! empty( $found_settings ) ) {
309
        foreach ( $found_settings as $key => $value ) {
310
311
            // settings used to have numeric keys, now they have keys that match the option ID. This ensures both methods work
312
            if ( is_numeric( $key ) ) {
313
                $key = $value['id'];
314
            }
315
316
            if ( ! isset( $input[ $key ] ) && isset( $wpinv_options[ $key ] ) ) {
317
                unset( $wpinv_options[ $key ] );
318
            }
319
        }
320
    }
321
322
    // Merge our new settings with the existing
323
    $output = array_merge( $wpinv_options, $input );
324
325
    add_settings_error( 'wpinv-notices', '', __( 'Settings updated.', 'invoicing' ), 'updated' );
326
327
    return $output;
328
}
329
add_filter( 'wpinv_settings_sanitize_text', 'trim', 10, 1 );
330
add_filter( 'wpinv_settings_sanitize_tax_rate', 'wpinv_sanitize_amount' );
331
332
function wpinv_settings_sanitize_tax_rates( $input ) {
333
    if ( ! wpinv_current_user_can_manage_invoicing() ) {
334
        return $input;
335
    }
336
337
    $new_rates = ! empty( $_POST['tax_rates'] ) ? wp_kses_post_deep( array_values( $_POST['tax_rates'] ) ) : array();
338
    $tax_rates = array();
339
340
    foreach ( $new_rates as $rate ) {
341
342
		$rate['rate']    = wpinv_sanitize_amount( $rate['rate'] );
343
		$rate['name']    = sanitize_text_field( $rate['name'] );
344
		$rate['state']   = sanitize_text_field( $rate['state'] );
345
		$rate['country'] = sanitize_text_field( $rate['country'] );
346
		$rate['global']  = empty( $rate['state'] );
347
		$tax_rates[]     = $rate;
348
349
	}
350
351
    update_option( 'wpinv_tax_rates', $tax_rates );
352
353
    return $input;
354
}
355
add_filter( 'wpinv_settings_taxes-rates_sanitize', 'wpinv_settings_sanitize_tax_rates' );
356
357
function wpinv_get_settings_tabs() {
358
    $tabs             = array();
359
    $tabs['general']  = __( 'General', 'invoicing' );
360
    $tabs['gateways'] = __( 'Payment Gateways', 'invoicing' );
361
    $tabs['taxes']    = __( 'Taxes', 'invoicing' );
362
	$tabs['emails']   = __( 'Emails', 'invoicing' );
363
364
	if ( count( getpaid_get_integration_settings() ) > 0 ) {
365
		$tabs['integrations'] = __( 'Integrations', 'invoicing' );
366
	}
367
368
    $tabs['privacy']  = __( 'Privacy', 'invoicing' );
369
    $tabs['misc']     = __( 'Misc', 'invoicing' );
370
    $tabs['tools']    = __( 'Tools', 'invoicing' );
371
372
    return apply_filters( 'wpinv_settings_tabs', $tabs );
373
}
374
375
function wpinv_get_settings_tab_sections( $tab = false ) {
376
    $tabs     = false;
377
    $sections = wpinv_get_registered_settings_sections();
378
379
    if ( $tab && ! empty( $sections[ $tab ] ) ) {
380
        $tabs = $sections[ $tab ];
381
    }
382
383
    return $tabs;
384
}
385
386
function wpinv_get_registered_settings_sections() {
387
    static $sections = false;
388
389
    if ( false !== $sections ) {
390
        return $sections;
391
    }
392
393
    $sections = array(
394
        'general'      => apply_filters(
395
            'wpinv_settings_sections_general',
396
            array(
397
				'main'             => __( 'General Settings', 'invoicing' ),
398
				'page_section'     => __( 'Page Settings', 'invoicing' ),
399
				'currency_section' => __( 'Currency Settings', 'invoicing' ),
400
				'labels'           => __( 'Label Texts', 'invoicing' ),
401
            )
402
        ),
403
        'gateways'     => apply_filters(
404
            'wpinv_settings_sections_gateways',
405
            array(
406
				'main' => __( 'Gateway Settings', 'invoicing' ),
407
            )
408
        ),
409
        'taxes'        => apply_filters(
410
            'wpinv_settings_sections_taxes',
411
            array(
412
				'main'  => __( 'Tax Settings', 'invoicing' ),
413
				'rates' => __( 'Tax Rates', 'invoicing' ),
414
				'vat'   => __( 'EU VAT Settings', 'invoicing' ),
415
            )
416
        ),
417
        'emails'       => apply_filters(
418
            'wpinv_settings_sections_emails',
419
            array(
420
				'main' => __( 'Email Settings', 'invoicing' ),
421
            )
422
        ),
423
424
		'integrations' => wp_list_pluck( getpaid_get_integration_settings(), 'label', 'id' ),
425
426
        'privacy'      => apply_filters(
427
            'wpinv_settings_sections_privacy',
428
            array(
429
				'main' => __( 'Privacy policy', 'invoicing' ),
430
            )
431
        ),
432
        'misc'         => apply_filters(
433
            'wpinv_settings_sections_misc',
434
            array(
435
				'main'       => __( 'Miscellaneous', 'invoicing' ),
436
				'custom-css' => __( 'Custom CSS', 'invoicing' ),
437
            )
438
        ),
439
        'tools'        => apply_filters(
440
            'wpinv_settings_sections_tools',
441
            array(
442
				'main' => __( 'Diagnostic Tools', 'invoicing' ),
443
            )
444
        ),
445
    );
446
447
    $sections = apply_filters( 'wpinv_settings_sections', $sections );
448
449
    return $sections;
450
}
451
452
function wpinv_get_pages( $with_slug = false, $default_label = null ) {
453
	$pages_options = array();
454
455
	if ( $default_label !== null && $default_label !== false ) {
456
		$pages_options = array( '' => $default_label ); // Blank option
457
	}
458
459
	$pages = get_pages();
460
	if ( $pages ) {
461
		foreach ( $pages as $page ) {
462
			$title = $with_slug ? $page->post_title . ' (' . $page->post_name . ')' : $page->post_title;
463
            $pages_options[ $page->ID ] = $title;
464
		}
465
	}
466
467
	return $pages_options;
468
}
469
470
function wpinv_header_callback( $args ) {
471
	if ( ! empty( $args['desc'] ) ) {
472
        echo wp_kses_post( $args['desc'] );
473
    }
474
}
475
476
function wpinv_hidden_callback( $args ) {
477
478
	$std     = isset( $args['std'] ) ? $args['std'] : '';
479
	$value   = wpinv_get_option( $args['id'], $std );
480
481
	if ( isset( $args['set_value'] ) ) {
482
		$value = $args['set_value'];
483
	}
484
485
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
486
		$args['readonly'] = true;
487
		$name  = '';
488
	} else {
489
		$name = 'wpinv_settings[' . esc_attr( $args['id'] ) . ']';
490
	}
491
492
	echo '<input type="hidden" id="wpinv_settings[' . esc_attr( $args['id'] ) . ']" name="' . esc_attr( $name ) . '" value="' . esc_attr( stripslashes( $value ) ) . '" />';
493
494
}
495
496
/**
497
 * Displays a checkbox settings callback.
498
 */
499
function wpinv_checkbox_callback( $args ) {
500
501
	$std = isset( $args['std'] ) ? $args['std'] : '';
502
	$std = wpinv_get_option( $args['id'], $std );
503
	$id  = esc_attr( $args['id'] );
504
505
	getpaid_hidden_field( "wpinv_settings[$id]", '0' );
506
	?>
507
		<fieldset>
508
			<label>
509
				<input id="wpinv-settings-<?php echo esc_attr( $id ); ?>" name="wpinv_settings[<?php echo esc_attr( $id ); ?>]" <?php checked( empty( $std ), false ); ?> value="1" type="checkbox">
510
				<?php echo wp_kses_post( $args['desc'] ); ?>
511
			</label>
512
		</fieldset>
513
	<?php
514
}
515
516
function wpinv_multicheck_callback( $args ) {
517
518
	$sanitize_id = wpinv_sanitize_key( $args['id'] );
519
	$class = ! empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
520
521
	if ( ! empty( $args['options'] ) ) {
522
523
		$std     = isset( $args['std'] ) ? $args['std'] : array();
524
		$value   = wpinv_get_option( $args['id'], $std );
525
526
		echo '<div class="wpi-mcheck-rows wpi-mcheck-' . esc_attr( $sanitize_id . $class ) . '">';
527
        foreach ( $args['options'] as $key => $option ) :
528
			$sanitize_key = esc_attr( wpinv_sanitize_key( $key ) );
529
			if ( in_array( $sanitize_key, $value ) ) {
530
				$enabled = $sanitize_key;
531
			} else {
532
				$enabled = null;
533
			}
534
			echo '<div class="wpi-mcheck-row"><input name="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']" id="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']" type="checkbox" value="' . esc_attr( $sanitize_key ) . '" ' . checked( $sanitize_key, $enabled, false ) . '/>&nbsp;';
535
			echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']">' . wp_kses_post( $option ) . '</label></div>';
536
		endforeach;
537
		echo '</div>';
538
		echo '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
539
	}
540
}
541
542
function wpinv_payment_icons_callback( $args ) {
543
544
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
545
	$value   = wpinv_get_option( $args['id'], false );
546
547
	if ( ! empty( $args['options'] ) ) {
548
		foreach ( $args['options'] as $key => $option ) {
549
            $sanitize_key = wpinv_sanitize_key( $key );
550
551
			if ( empty( $value ) ) {
552
				$enabled = $option;
553
			} else {
554
				$enabled = null;
555
			}
556
557
			echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']" style="margin-right:10px;line-height:16px;height:16px;display:inline-block;">';
558
559
				echo '<input name="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']" id="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']" type="checkbox" value="' . esc_attr( $option ) . '" ' . checked( $option, $enabled, false ) . '/>&nbsp;';
560
561
				if ( wpinv_string_is_image_url( $key ) ) {
562
				echo '<img class="payment-icon" src="' . esc_url( $key ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
563
				} else {
564
				$card = strtolower( str_replace( ' ', '', $option ) );
565
566
				if ( has_filter( 'wpinv_accepted_payment_' . $card . '_image' ) ) {
567
					$image = apply_filters( 'wpinv_accepted_payment_' . $card . '_image', '' );
568
					} else {
569
					$image       = wpinv_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', false );
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $template_path of wpinv_locate_template(). ( Ignorable by Annotation )

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

569
					$image       = wpinv_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', /** @scrutinizer ignore-type */ false );
Loading history...
570
					$content_dir = WP_CONTENT_DIR;
571
572
					if ( function_exists( 'wp_normalize_path' ) ) {
573
						// Replaces backslashes with forward slashes for Windows systems
574
						$image = wp_normalize_path( $image );
575
						$content_dir = wp_normalize_path( $content_dir );
576
						}
577
578
					$image = str_replace( $content_dir, content_url(), $image );
579
					}
580
581
				echo '<img class="payment-icon" src="' . esc_url( $image ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
582
				}
583
			echo wp_kses_post( $option ) . '</label>';
584
		}
585
		echo '<p class="description" style="margin-top:16px;">' . wp_kses_post( $args['desc'] ) . '</p>';
586
	}
587
}
588
589
/**
590
 * Displays a radio settings field.
591
 */
592
function wpinv_radio_callback( $args ) {
593
594
	$std = isset( $args['std'] ) ? $args['std'] : '';
595
	$std = wpinv_get_option( $args['id'], $std );
596
	?>
597
		<fieldset>
598
			<ul id="wpinv-settings-<?php echo esc_attr( $args['id'] ); ?>" style="margin-top: 0;">
599
				<?php foreach ( $args['options'] as $key => $option ) : ?>
600
					<li>
601
						<label>
602
							<input name="wpinv_settings[<?php echo esc_attr( $args['id'] ); ?>]" <?php checked( $std, $key ); ?> value="<?php echo esc_attr( $key ); ?>" type="radio">
603
							<?php echo wp_kses_post( $option ); ?>
604
						</label>
605
					</li>
606
				<?php endforeach; ?>
607
			</ul>
608
		</fieldset>
609
	<?php
610
	getpaid_settings_description_callback( $args );
611
}
612
613
/**
614
 * Displays a description if available.
615
 */
616
function getpaid_settings_description_callback( $args ) {
617
618
	if ( ! empty( $args['desc'] ) ) {
619
		$description = $args['desc'];
620
		echo wp_kses_post( "<p class='description'>$description</p>" );
621
	}
622
623
}
624
625
/**
626
 * Displays a list of available gateways.
627
 */
628
function wpinv_gateways_callback() {
629
630
	?>
631
		</td>
632
	</tr>
633
	<tr class="bsui">
634
    	<td colspan="2" class="p-0">
635
			<?php include plugin_dir_path( __FILE__ ) . 'views/html-gateways-edit.php'; ?>
636
637
	<?php
638
}
639
640
function wpinv_gateway_select_callback( $args ) {
641
642
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
643
    $class = ! empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
644
	$std     = isset( $args['std'] ) ? $args['std'] : '';
645
	$value   = wpinv_get_option( $args['id'], $std );
646
647
	echo '<select name="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" class="' . esc_attr( $class ) . '" >';
648
649
	foreach ( $args['options'] as $key => $option ) :
650
651
		echo '<option value="' . esc_attr( $key ) . '" ';
652
653
		if ( isset( $args['selected'] ) && $args['selected'] !== null && $args['selected'] !== false ) {
654
            selected( $key, $args['selected'] );
655
        } else {
656
            selected( $key, $value );
657
        }
658
659
		echo '>' . esc_html( $option['admin_label'] ) . '</option>';
660
	endforeach;
661
662
	echo '</select>';
663
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
664
}
665
666
/**
667
 * Generates attributes.
668
 *
669
 * @param array $args
670
 * @return string
671
 */
672
function wpinv_settings_attrs_helper( $args ) {
673
674
	$value = isset( $args['std'] ) ? $args['std'] : '';
675
	$id    = esc_attr( $args['id'] );
676
	$value = is_scalar( $value ) ? $value : '';
677
678
	$attrs = array(
679
		'name'     => ! empty( $args['faux'] ) ? false : "wpinv_settings[$id]",
680
		'readonly' => ! empty( $args['faux'] ),
681
		'value'    => ! empty( $args['faux'] ) ? $value : wpinv_get_option( $args['id'], $value ),
682
		'id'       => 'wpinv-settings-' . $args['id'],
683
		'style'    => $args['style'],
684
		'class'    => $args['class'],
685
		'placeholder' => $args['placeholder'],
686
		'data-placeholder' => $args['placeholder'],
687
	);
688
689
	if ( ! empty( $args['onchange'] ) ) {
690
		$attrs['onchange'] = $args['onchange'];
691
	}
692
693
	foreach ( $attrs as $key => $value ) {
694
695
		if ( false === $value ) {
696
			continue;
697
		}
698
699
		if ( true === $value ) {
700
			echo ' ' . esc_attr( $key );
701
		} else {
702
			echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
703
		}
704
705
	}
706
707
}
708
709
/**
710
 * Displays a text input settings callback.
711
 */
712
function wpinv_text_callback( $args ) {
713
714
	$desc = empty( $desc ) ? '' : "<p class='description'>$desc</p>";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $desc seems to never exist and therefore empty should always be true.
Loading history...
715
716
	?>
717
		<label style="width: 100%;">
718
			<input type="text" <?php wpinv_settings_attrs_helper( $args ); ?>>
719
			<?php echo wp_kses_post( $desc ); ?>
720
		</label>
721
	<?php
722
723
}
724
725
/**
726
 * Displays a number input settings callback.
727
 */
728
function wpinv_number_callback( $args ) {
729
730
	$desc = empty( $desc ) ? '' : "<p class='description'>$desc</p>";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $desc seems to never exist and therefore empty should always be true.
Loading history...
731
732
	?>
733
		<label style="width: 100%;">
734
			<input type="number" step="<?php echo floatval( $args['step'] ); ?>" max="<?php echo intval( $args['max'] ); ?>" min="<?php echo intval( $args['min'] ); ?>" <?php wpinv_settings_attrs_helper( $args ); ?>>
735
			<?php echo wp_kses_post( $desc ); ?>
736
		</label>
737
	<?php
738
739
}
740
741
function wpinv_textarea_callback( $args ) {
742
743
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
744
	$std     = isset( $args['std'] ) ? $args['std'] : '';
745
	$value   = wpinv_get_option( $args['id'], $std );
746
747
    $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
748
    $class = ( isset( $args['class'] ) && ! is_null( $args['class'] ) ) ? $args['class'] : 'large-text';
749
750
	echo '<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>';
751
	echo '<br /><label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
752
753
}
754
755
function wpinv_password_callback( $args ) {
756
757
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
758
	$std     = isset( $args['std'] ) ? $args['std'] : '';
759
	$value   = wpinv_get_option( $args['id'], $std );
760
761
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
762
	echo '<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 ) . '"/>';
763
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
764
765
}
766
767
function wpinv_missing_callback( $args ) {
768
	printf(
769
		__( 'The callback function used for the %s setting is missing.', 'invoicing' ),
770
		'<strong>' . $args['id'] . '</strong>'
771
	);
772
}
773
774
/**
775
 * Displays a number input settings callback.
776
 */
777
function wpinv_select_callback( $args ) {
778
779
	$desc   = wp_kses_post( $args['desc'] );
780
	$desc   = empty( $desc ) ? '' : "<p class='description'>$desc</p>";
781
	$value  = isset( $args['std'] ) ? $args['std'] : '';
782
	$value  = wpinv_get_option( $args['id'], $value );
783
	$rand   = uniqid( 'random_id' );
784
785
	?>
786
		<label style="width: 100%;">
787
			<select <?php wpinv_settings_attrs_helper( $args ); ?> data-allow-clear="true">
788
				<?php foreach ( $args['options'] as $option => $name ) : ?>
789
					<option value="<?php echo esc_attr( $option ); ?>" <?php echo selected( $option, $value ); ?>><?php echo wpinv_clean( $name ); ?></option>
0 ignored issues
show
Bug introduced by
Are you sure wpinv_clean($name) of type array|string can be used in echo? ( Ignorable by Annotation )

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

789
					<option value="<?php echo esc_attr( $option ); ?>" <?php echo selected( $option, $value ); ?>><?php echo /** @scrutinizer ignore-type */ wpinv_clean( $name ); ?></option>
Loading history...
790
				<?php endforeach; ?>
791
			</select>
792
793
			<?php if ( substr( $args['id'], -5 ) === '_page' && is_numeric( $value ) ) : ?>
794
				<a href="<?php echo get_edit_post_link( $value ); ?>" target="_blank" class="button getpaid-page-setting-edit"><?php esc_html_e( 'Edit Page', 'invoicing' ); ?></a>
0 ignored issues
show
Bug introduced by
$value of type string is incompatible with the type WP_Post|integer expected by parameter $id of get_edit_post_link(). ( Ignorable by Annotation )

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

794
				<a href="<?php echo get_edit_post_link( /** @scrutinizer ignore-type */ $value ); ?>" target="_blank" class="button getpaid-page-setting-edit"><?php esc_html_e( 'Edit Page', 'invoicing' ); ?></a>
Loading history...
795
			<?php endif; ?>
796
797
			<?php if ( substr( $args['id'], -5 ) === '_page' && ! empty( $args['default_content'] ) ) : ?>
798
				&nbsp;<a href="#TB_inline?&width=400&height=550&inlineId=<?php echo $rand; ?>" class="button thickbox getpaid-page-setting-view-default"><?php esc_html_e( 'View Default Content', 'invoicing' ); ?></a>
799
				<div id='<?php echo $rand; ?>' style='display:none;'>
800
					<div>
801
						<h3><?php esc_html_e( 'Original Content', 'invoicing' ); ?></h3>
802
						<textarea readonly onclick="this.select()" rows="8" style="width: 100%;"><?php echo gepaid_trim_lines( wp_kses_post( $args['default_content'] ) ); ?></textarea>
803
						<h3><?php esc_html_e( 'Current Content', 'invoicing' ); ?></h3>
804
						<textarea readonly onclick="this.select()" rows="8" style="width: 100%;"><?php $_post = get_post( $value ); echo empty( $_post ) ? '' : gepaid_trim_lines( wp_kses_post( $_post->post_content ) ); ?></textarea>
805
					</div>
806
				</div>
807
			<?php endif; ?>
808
809
			<?php echo $desc; ?>
810
		</label>
811
	<?php
812
813
}
814
815
function wpinv_color_select_callback( $args ) {
816
817
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
818
	$std     = isset( $args['std'] ) ? $args['std'] : '';
819
	$value   = wpinv_get_option( $args['id'], $std );
820
821
	echo '<select id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"/>';
822
823
	foreach ( $args['options'] as $option => $color ) {
824
		echo '<option value="' . esc_attr( $option ) . '" ' . selected( $option, $value ) . '>' . esc_html( $color['label'] ) . '</option>';
825
	}
826
827
	echo '</select>';
828
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
829
830
}
831
832
function wpinv_rich_editor_callback( $args ) {
833
	global $wp_version;
834
835
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
836
837
	$std     = isset( $args['std'] ) ? $args['std'] : '';
838
	$value   = wpinv_get_option( $args['id'], $std );
839
840
	if ( ! empty( $args['allow_blank'] ) && empty( $value ) ) {
841
		$value = $std;
842
	}
843
844
	$rows = isset( $args['size'] ) ? $args['size'] : 20;
845
846
	echo '<div class="getpaid-settings-editor-input">';
847
	if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) {
848
		wp_editor(
849
            stripslashes( $value ),
850
            'wpinv_settings_' . esc_attr( $args['id'] ),
851
            array(
852
				'textarea_name' => 'wpinv_settings[' . esc_attr( $args['id'] ) . ']',
853
				'textarea_rows' => absint( $rows ),
854
				'media_buttons' => false,
855
            )
856
        );
857
	} else {
858
		echo '<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>';
859
	}
860
861
	echo '</div><br/><label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
862
863
}
864
865
function wpinv_upload_callback( $args ) {
866
867
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
868
869
	$std     = isset( $args['std'] ) ? $args['std'] : '';
870
	$value   = wpinv_get_option( $args['id'], $std );
871
872
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
873
	echo '<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 ) ) . '"/>';
874
	echo '<span>&nbsp;<input type="button" class="wpinv_settings_upload_button button-secondary" value="' . __( 'Upload File', 'invoicing' ) . '"/></span>';
875
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
876
877
}
878
879
function wpinv_color_callback( $args ) {
880
881
	$std         = isset( $args['std'] ) ? $args['std'] : '';
882
	$value       = wpinv_get_option( $args['id'], $std );
883
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
884
885
	echo '<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( $std ) . '" />';
886
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
887
888
}
889
890
function wpinv_country_states_callback( $args ) {
891
892
	$std     = isset( $args['std'] ) ? $args['std'] : '';
893
	$value   = wpinv_get_option( $args['id'], $std );
894
895
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
896
897
	if ( isset( $args['placeholder'] ) ) {
898
		$placeholder = $args['placeholder'];
899
	} else {
900
		$placeholder = '';
901
	}
902
903
	$states = wpinv_get_country_states();
904
905
	$class = empty( $states ) ? ' class="wpinv-no-states"' : ' class="wpi_select2"';
906
	echo '<select id="wpinv_settings[' . $sanitize_id . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"' . $class . 'data-placeholder="' . esc_html( $placeholder ) . '"/>';
907
908
	foreach ( $states as $option => $name ) {
909
		echo '<option value="' . esc_attr( $option ) . '" ' . selected( $option, $value ) . '>' . esc_html( $name ) . '</option>';
910
	}
911
912
	echo '</select>';
913
	echo '<label for="wpinv_settings[' . $sanitize_id . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
914
915
}
916
917
/**
918
 * Displays the tax rates edit table.
919
 */
920
function wpinv_tax_rates_callback() {
921
922
	?>
923
		</td>
924
	</tr>
925
	<tr class="bsui">
926
    	<td colspan="2" class="p-0">
927
			<?php include plugin_dir_path( __FILE__ ) . 'views/html-tax-rates-edit.php'; ?>
928
929
	<?php
930
931
}
932
933
/**
934
 * Displays a tax rate' edit row.
935
 */
936
function wpinv_tax_rate_callback( $tax_rate, $key, $echo = true ) {
937
	ob_start();
938
939
	$key                      = sanitize_key( $key );
940
	$tax_rate['reduced_rate'] = empty( $tax_rate['reduced_rate'] ) ? 0 : $tax_rate['reduced_rate'];
941
	include plugin_dir_path( __FILE__ ) . 'views/html-tax-rate-edit.php';
942
943
	if ( $echo ) {
944
		echo ob_get_clean();
945
	} else {
946
		return ob_get_clean();
947
	}
948
949
}
950
951
952
function wpinv_tools_callback( $args ) {
953
    ?>
954
    </td><tr>
955
    <td colspan="2" class="wpinv_tools_tdbox">
956
    <?php
957
    if ( $args['desc'] ) {
958
?>
959
<p><?php echo $args['desc']; ?></p><?php } ?>
960
    <?php do_action( 'wpinv_tools_before' ); ?>
961
    <table id="wpinv_tools_table" class="wp-list-table widefat fixed posts">
962
        <thead>
963
            <tr>
964
                <th scope="col" class="wpinv-th-tool"><?php esc_html_e( 'Tool', 'invoicing' ); ?></th>
965
                <th scope="col" class="wpinv-th-desc"><?php esc_html_e( 'Description', 'invoicing' ); ?></th>
966
                <th scope="col" class="wpinv-th-action"><?php esc_html_e( 'Action', 'invoicing' ); ?></th>
967
            </tr>
968
        </thead>
969
970
        <tbody>
971
			<tr>
972
                <td><?php esc_html_e( 'Check Pages', 'invoicing' ); ?></td>
973
                <td>
974
                    <small><?php esc_html_e( 'Creates any missing GetPaid pages.', 'invoicing' ); ?></small>
975
                </td>
976
                <td>
977
					<a href="
978
                    <?php
979
						echo esc_url(
980
							wp_nonce_url(
981
								add_query_arg( 'getpaid-admin-action', 'create_missing_pages' ),
982
								'getpaid-nonce',
983
								'getpaid-nonce'
984
							)
985
						);
986
					?>
987
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
988
                </td>
989
            </tr>
990
			<tr>
991
                <td><?php esc_html_e( 'Create Database Tables', 'invoicing' ); ?></td>
992
                <td>
993
                    <small><?php esc_html_e( 'Run this tool to create any missing database tables.', 'invoicing' ); ?></small>
994
                </td>
995
                <td>
996
					<a href="
997
                    <?php
998
						echo esc_url(
999
							wp_nonce_url(
1000
								add_query_arg( 'getpaid-admin-action', 'create_missing_tables' ),
1001
								'getpaid-nonce',
1002
								'getpaid-nonce'
1003
							)
1004
						);
1005
					?>
1006
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1007
                </td>
1008
            </tr>
1009
			<tr>
1010
                <td><?php esc_html_e( 'Migrate old invoices', 'invoicing' ); ?></td>
1011
                <td>
1012
                    <small><?php esc_html_e( 'If your old invoices were not migrated after updating from Invoicing to GetPaid, you can use this tool to migrate them.', 'invoicing' ); ?></small>
1013
                </td>
1014
                <td>
1015
					<a href="
1016
                    <?php
1017
						echo esc_url(
1018
							wp_nonce_url(
1019
								add_query_arg( 'getpaid-admin-action', 'migrate_old_invoices' ),
1020
								'getpaid-nonce',
1021
								'getpaid-nonce'
1022
							)
1023
						);
1024
					?>
1025
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1026
                </td>
1027
            </tr>
1028
1029
			<tr>
1030
                <td><?php esc_html_e( 'Recalculate Discounts', 'invoicing' ); ?></td>
1031
                <td>
1032
                    <small><?php esc_html_e( 'Recalculate discounts for existing invoices that have discount codes but are not discounted.', 'invoicing' ); ?></small>
1033
                </td>
1034
                <td>
1035
					<a href="
1036
                    <?php
1037
						echo esc_url(
1038
							wp_nonce_url(
1039
								add_query_arg( 'getpaid-admin-action', 'recalculate_discounts' ),
1040
								'getpaid-nonce',
1041
								'getpaid-nonce'
1042
							)
1043
						);
1044
					?>
1045
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1046
                </td>
1047
            </tr>
1048
1049
			<tr>
1050
                <td><?php esc_html_e( 'Set-up Wizard', 'invoicing' ); ?></td>
1051
                <td>
1052
                    <small><?php esc_html_e( 'Launch the quick set-up wizard.', 'invoicing' ); ?></small>
1053
                </td>
1054
                <td>
1055
					<a href="
1056
                    <?php
1057
						echo esc_url( admin_url( 'index.php?page=gp-setup' ) );
1058
					?>
1059
                    " class="button button-primary"><?php esc_html_e( 'Launch', 'invoicing' ); ?></a>
1060
                </td>
1061
            </tr>
1062
1063
			<?php do_action( 'wpinv_tools_row' ); ?>
1064
        </tbody>
1065
    </table>
1066
    <?php do_action( 'wpinv_tools_after' ); ?>
1067
    <?php
1068
}
1069
1070
1071
function wpinv_descriptive_text_callback( $args ) {
1072
	echo wp_kses_post( $args['desc'] );
1073
}
1074
1075
function wpinv_raw_html_callback( $args ) {
1076
	echo wp_kses_post( $args['desc'] );
1077
}
1078
1079
function wpinv_hook_callback( $args ) {
1080
	do_action( 'wpinv_' . $args['id'], $args );
1081
}
1082
1083
function wpinv_set_settings_cap() {
1084
	return wpinv_get_capability();
1085
}
1086
add_filter( 'option_page_capability_wpinv_settings', 'wpinv_set_settings_cap' );
1087
1088
1089
function wpinv_on_update_settings( $old_value, $value, $option ) {
1090
    $old = ! empty( $old_value['remove_data_on_unistall'] ) ? 1 : '';
1091
    $new = ! empty( $value['remove_data_on_unistall'] ) ? 1 : '';
1092
1093
    if ( $old != $new ) {
1094
        update_option( 'wpinv_remove_data_on_invoice_unistall', $new );
1095
    }
1096
}
1097
add_action( 'update_option_wpinv_settings', 'wpinv_on_update_settings', 10, 3 );
1098
1099
/**
1100
 * Returns the merge tags help text.
1101
 *
1102
 * @since    2.1.8
1103
 *
1104
 * @return string
1105
 */
1106
function wpinv_get_merge_tags_help_text( $subscription = false ) {
1107
1108
	$url  = $subscription ? 'https://gist.github.com/picocodes/3d213982d57c34edf7a46fd3f0e8583e' : 'https://gist.github.com/picocodes/43bdc4d4bbba844534b2722e2af0b58f';
1109
	$link = sprintf(
1110
		'<strong><a href="%s" target="_blank">%s</a></strong>',
1111
		$url,
1112
		esc_html__( 'View available merge tags.', 'wpinv-quotes' )
1113
	);
1114
1115
	$description = esc_html__( 'The content of the email (Merge Tags and HTML are allowed).', 'invoicing' );
1116
1117
	return "$description $link";
1118
1119
}
1120