wpinv_update_option()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 18
rs 10
c 0
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
	do_action( 'getpaid_before_register_settings' );
148
149
    // Loop through all tabs.
150
    foreach ( wpinv_get_registered_settings() as $tab => $sections ) {
151
152
        // In each tab, loop through sections.
153
        foreach ( $sections as $section => $settings ) {
154
155
            // Check for backwards compatibility
156
            $section_tabs = wpinv_get_settings_tab_sections( $tab );
157
            if ( ! is_array( $section_tabs ) || ! array_key_exists( $section, $section_tabs ) ) {
158
                $section = 'main';
159
                $settings = $sections;
160
            }
161
162
			do_action( "getpaid_register_{$tab}_{$section}" );
163
164
            // Register the setting section.
165
            add_settings_section(
166
                'wpinv_settings_' . $tab . '_' . $section,
167
                __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...
168
                '__return_false',
169
                'wpinv_settings_' . $tab . '_' . $section
170
            );
171
172
            foreach ( $settings as $option ) {
173
                if ( ! empty( $option['id'] ) ) {
174
                    wpinv_register_settings_option( $tab, $section, $option );
175
                }
176
            }
177
}
178
    }
179
180
    // Creates our settings in the options table.
181
    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

181
    register_setting( 'wpinv_settings', 'wpinv_settings', /** @scrutinizer ignore-type */ 'wpinv_settings_sanitize' );
Loading history...
182
183
	do_action( 'getpaid_after_register_settings' );
184
}
185
add_action( 'admin_init', 'wpinv_register_settings' );
186
187
/**
188
 * Register a single settings option.
189
 *
190
 * @param string $tab
191
 * @param string $section
192
 * @param string $option
193
 *
194
 */
195
function wpinv_register_settings_option( $tab, $section, $option ) {
196
197
    $name       = isset( $option['name'] ) ? $option['name'] : '';
198
    $cb         = "wpinv_{$option['type']}_callback";
199
    $section    = "wpinv_settings_{$tab}_$section";
200
	$is_wizzard = is_admin() && isset( $_GET['page'] ) && 'gp-setup' == $_GET['page'];
201
202
	if ( isset( $option['desc'] ) && ( ! $is_wizzard && ! empty( $option['help-tip'] ) ) ) {
203
		$tip   = wpinv_clean( $option['desc'] );
204
		$name .= "<span class='dashicons dashicons-editor-help wpi-help-tip' title='$tip'></span>";
205
		unset( $option['desc'] );
206
	}
207
208
    // Loop through all tabs.
209
    add_settings_field(
210
        'wpinv_settings[' . $option['id'] . ']',
211
        $name,
212
        function_exists( $cb ) ? $cb : 'wpinv_missing_callback',
213
        $section,
214
        $section,
215
        array(
216
            'section'         => $section,
217
            'id'              => isset( $option['id'] ) ? $option['id'] : uniqid( 'wpinv-' ),
218
            'desc'            => isset( $option['desc'] ) ? $option['desc'] : '',
219
            'name'            => $name,
220
            'size'            => isset( $option['size'] ) ? $option['size'] : null,
221
            'options'         => isset( $option['options'] ) ? $option['options'] : '',
222
            'selected'        => isset( $option['selected'] ) ? $option['selected'] : null,
223
            'std'             => isset( $option['std'] ) ? $option['std'] : '',
224
            'min'             => isset( $option['min'] ) ? $option['min'] : 0,
225
            'max'             => isset( $option['max'] ) ? $option['max'] : 999999,
226
            'step'            => isset( $option['step'] ) ? $option['step'] : 1,
227
            'placeholder'     => isset( $option['placeholder'] ) ? $option['placeholder'] : null,
228
            'allow_blank'     => isset( $option['allow_blank'] ) ? $option['allow_blank'] : true,
229
            'readonly'        => isset( $option['readonly'] ) ? $option['readonly'] : false,
230
            'faux'            => isset( $option['faux'] ) ? $option['faux'] : false,
231
            'onchange'        => isset( $option['onchange'] ) ? $option['onchange'] : '',
232
            'custom'          => isset( $option['custom'] ) ? $option['custom'] : '',
233
			'default_content' => isset( $option['default_content'] ) ? $option['default_content'] : '',
234
			'class'           => isset( $option['class'] ) ? $option['class'] : '',
235
			'style'           => isset( $option['style'] ) ? $option['style'] : '',
236
            'cols'            => isset( $option['cols'] ) && (int) $option['cols'] > 0 ? (int) $option['cols'] : 50,
237
            'rows'            => isset( $option['rows'] ) && (int) $option['rows'] > 0 ? (int) $option['rows'] : 5,
238
        )
239
    );
240
241
}
242
243
/**
244
 * Returns an array of all registered settings.
245
 *
246
 * @return array
247
 */
248
function wpinv_get_registered_settings() {
249
	return array_filter( apply_filters( 'wpinv_registered_settings', wpinv_get_data( 'admin-settings' ) ) );
250
}
251
252
/**
253
 * Returns an array of all integration settings.
254
 *
255
 * @return array
256
 */
257
function getpaid_get_integration_settings() {
258
    return apply_filters( 'getpaid_integration_settings', array() );
259
}
260
261
/**
262
 * Sanitizes settings before they are saved.
263
 *
264
 * @return array
265
 */
266
function wpinv_settings_sanitize( $input = array() ) {
267
268
	$wpinv_options = wpinv_get_options();
269
	$raw_referrer  = wp_get_raw_referer();
270
271
    if ( empty( $raw_referrer ) ) {
272
		return array_merge( $wpinv_options, $input );
273
    }
274
275
    wp_parse_str( $raw_referrer, $referrer );
276
277
	if ( in_array( 'gp-setup', $referrer ) ) {
278
		return array_merge( $wpinv_options, $input );
279
	}
280
281
    $settings = wpinv_get_registered_settings();
282
    $tab      = isset( $referrer['tab'] ) ? $referrer['tab'] : 'general';
283
    $section  = isset( $referrer['section'] ) ? $referrer['section'] : 'main';
284
285
    $input = $input ? $input : array();
286
    $input = apply_filters( 'wpinv_settings_tab_' . $tab . '_sanitize', $input );
287
    $input = apply_filters( 'wpinv_settings_' . $tab . '-' . $section . '_sanitize', $input );
288
289
    // Loop through each setting being saved and pass it through a sanitization filter
290
    foreach ( $input as $key => $value ) {
291
292
        // Get the setting type (checkbox, select, etc)
293
        $type = isset( $settings[ $tab ][ $section ][ $key ]['type'] ) ? $settings[ $tab ][ $section ][ $key ]['type'] : false;
294
295
        if ( $type ) {
296
            // Field type specific filter
297
            $input[ $key ] = apply_filters( "wpinv_settings_sanitize_$type", $value, $key );
298
        }
299
300
        // General filter
301
		$input[ $key ] = apply_filters( 'wpinv_settings_sanitize', $input[ $key ], $key );
302
303
		// Key specific filter.
304
		$input[ $key ] = apply_filters( "wpinv_settings_sanitize_$key", $input[ $key ] );
305
    }
306
307
    // Loop through the whitelist and unset any that are empty for the tab being saved
308
    $main_settings    = isset( $settings[ $tab ] ) ? $settings[ $tab ] : array(); // Check for extensions that aren't using new sections
309
    $section_settings = ! empty( $settings[ $tab ][ $section ] ) ? $settings[ $tab ][ $section ] : array();
310
311
    $found_settings   = array_merge( $main_settings, $section_settings );
312
313
    if ( ! empty( $found_settings ) ) {
314
        foreach ( $found_settings as $key => $value ) {
315
316
            // settings used to have numeric keys, now they have keys that match the option ID. This ensures both methods work
317
            if ( is_numeric( $key ) ) {
318
                $key = $value['id'];
319
            }
320
321
            if ( ! isset( $input[ $key ] ) && isset( $wpinv_options[ $key ] ) ) {
322
                unset( $wpinv_options[ $key ] );
323
            }
324
        }
325
    }
326
327
    // Merge our new settings with the existing
328
    $output = array_merge( $wpinv_options, $input );
329
330
    add_settings_error( 'wpinv-notices', '', __( 'Settings updated.', 'invoicing' ), 'updated' );
331
332
    return $output;
333
}
334
add_filter( 'wpinv_settings_sanitize_text', 'trim', 10, 1 );
335
add_filter( 'wpinv_settings_sanitize_tax_rate', 'wpinv_sanitize_amount' );
336
337
function wpinv_settings_sanitize_tax_rates( $input ) {
338
    if ( ! wpinv_current_user_can_manage_invoicing() ) {
339
        return $input;
340
    }
341
342
    $new_rates = ! empty( $_POST['tax_rates'] ) ? wp_kses_post_deep( array_values( $_POST['tax_rates'] ) ) : array();
343
    $tax_rates = array();
344
345
    foreach ( $new_rates as $rate ) {
346
347
		$rate['rate']    = wpinv_sanitize_amount( $rate['rate'] );
348
		$rate['name']    = sanitize_text_field( $rate['name'] );
349
		$rate['state']   = sanitize_text_field( $rate['state'] );
350
		$rate['country'] = sanitize_text_field( $rate['country'] );
351
		$rate['global']  = empty( $rate['state'] );
352
		$tax_rates[]     = $rate;
353
354
	}
355
356
    update_option( 'wpinv_tax_rates', $tax_rates );
357
358
    return $input;
359
}
360
add_filter( 'wpinv_settings_taxes-rates_sanitize', 'wpinv_settings_sanitize_tax_rates' );
361
362
function wpinv_settings_sanitize_tax_rules( $input ) {
363
    if ( ! wpinv_current_user_can_manage_invoicing() ) {
364
        return $input;
365
    }
366
367
	if ( empty( $_POST['wpinv_tax_rules_nonce'] ) || ! wp_verify_nonce( $_POST['wpinv_tax_rules_nonce'], 'wpinv_tax_rules' ) ) {
368
		return $input;
369
	}
370
371
    $new_rules = ! empty( $_POST['tax_rules'] ) ? wp_kses_post_deep( array_values( $_POST['tax_rules'] ) ) : array();
372
    $tax_rules = array();
373
374
    foreach ( $new_rules as $rule ) {
375
376
		$rule['key']      = sanitize_title_with_dashes( $rule['key'] );
377
		$rule['label']    = sanitize_text_field( $rule['label'] );
378
		$rule['tax_base'] = sanitize_text_field( $rule['tax_base'] );
379
		$tax_rules[]      = $rule;
380
381
	}
382
383
    update_option( 'wpinv_tax_rules', $tax_rules );
384
385
    return $input;
386
}
387
add_filter( 'wpinv_settings_taxes-rules_sanitize', 'wpinv_settings_sanitize_tax_rules' );
388
389
function wpinv_get_settings_tabs() {
390
    $tabs             = array();
391
    $tabs['general']  = __( 'General', 'invoicing' );
392
    $tabs['gateways'] = __( 'Payment Gateways', 'invoicing' );
393
    $tabs['taxes']    = __( 'Taxes', 'invoicing' );
394
	$tabs['emails']   = __( 'Emails', 'invoicing' );
395
396
	if ( count( getpaid_get_integration_settings() ) > 0 ) {
397
		$tabs['integrations'] = __( 'Integrations', 'invoicing' );
398
	}
399
400
    $tabs['privacy']  = __( 'Privacy', 'invoicing' );
401
    $tabs['misc']     = __( 'Misc', 'invoicing' );
402
    $tabs['tools']    = __( 'Tools', 'invoicing' );
403
404
    return apply_filters( 'wpinv_settings_tabs', $tabs );
405
}
406
407
function wpinv_get_settings_tab_sections( $tab = false ) {
408
    $tabs     = false;
409
    $sections = wpinv_get_registered_settings_sections();
410
411
    if ( $tab && ! empty( $sections[ $tab ] ) ) {
412
        $tabs = $sections[ $tab ];
413
    }
414
415
    return $tabs;
416
}
417
418
function wpinv_get_registered_settings_sections() {
419
    static $sections = false;
420
421
    if ( false !== $sections ) {
422
        return $sections;
423
    }
424
425
    $sections = array(
426
        'general'      => apply_filters(
427
            'wpinv_settings_sections_general',
428
            array(
429
				'main'             => __( 'General Settings', 'invoicing' ),
430
				'page_section'     => __( 'Page Settings', 'invoicing' ),
431
				'currency_section' => __( 'Currency Settings', 'invoicing' ),
432
				'labels'           => __( 'Label Texts', 'invoicing' ),
433
            )
434
        ),
435
        'gateways'     => apply_filters(
436
            'wpinv_settings_sections_gateways',
437
            array(
438
				'main' => __( 'Gateway Settings', 'invoicing' ),
439
            )
440
        ),
441
        'taxes'        => apply_filters(
442
            'wpinv_settings_sections_taxes',
443
            array(
444
				'main'  => __( 'Tax Settings', 'invoicing' ),
445
				'rules' => __( 'Tax Rules', 'invoicing' ),
446
				'rates' => __( 'Tax Rates', 'invoicing' ),
447
				'vat'   => __( 'EU VAT Settings', 'invoicing' ),
448
            )
449
        ),
450
        'emails'       => apply_filters(
451
            'wpinv_settings_sections_emails',
452
            array(
453
				'main' => __( 'Email Settings', 'invoicing' ),
454
            )
455
        ),
456
457
		'integrations' => wp_list_pluck( getpaid_get_integration_settings(), 'label', 'id' ),
458
459
        'privacy'      => apply_filters(
460
            'wpinv_settings_sections_privacy',
461
            array(
462
				'main' => __( 'Privacy policy', 'invoicing' ),
463
            )
464
        ),
465
        'misc'         => apply_filters(
466
            'wpinv_settings_sections_misc',
467
            array(
468
				'main'       => __( 'Miscellaneous', 'invoicing' ),
469
				'custom-css' => __( 'Custom CSS', 'invoicing' ),
470
            )
471
        ),
472
        'tools'        => apply_filters(
473
            'wpinv_settings_sections_tools',
474
            array(
475
				'main' => __( 'Diagnostic Tools', 'invoicing' ),
476
            )
477
        ),
478
    );
479
480
    $sections = apply_filters( 'wpinv_settings_sections', $sections );
481
482
    return $sections;
483
}
484
485
function wpinv_get_pages( $with_slug = false, $default_label = null ) {
486
    global $wpdb, $gp_tmpl_page_options;
487
488
    // Same function, lets not call it twice if we don't need to.
489
    if ( function_exists( 'sd_template_page_options' ) ) {
490
        $args = array(
491
            'with_slug' => $with_slug,
492
            'default_label' => $default_label
493
        );
494
495
        return sd_template_page_options( $args );
496
    }
497
498
    if ( ! empty( $gp_tmpl_page_options ) ) {
499
        return $gp_tmpl_page_options;
500
    }
501
502
    $exclude_pages = array();
503
    if ( $page_on_front = get_option( 'page_on_front' ) ) {
504
        $exclude_pages[] = $page_on_front;
505
    }
506
507
    if ( $page_for_posts = get_option( 'page_for_posts' ) ) {
508
        $exclude_pages[] = $page_for_posts;
509
    }
510
511
    $exclude_pages_placeholders = '';
512
    if ( ! empty( $exclude_pages ) ) {
513
        // Sanitize the array of excluded pages and implode it for the SQL query
514
        $exclude_pages_placeholders = implode(',', array_fill(0, count($exclude_pages), '%d'));
515
    }
516
517
    // Prepare the base SQL query, including child_of = 0 (only root-level pages)
518
    $sql = "
519
		SELECT ID, post_title, post_name
520
		FROM $wpdb->posts
521
		WHERE post_type = 'page'
522
		AND post_status = 'publish'
523
	";
524
525
    // Add the exclusion if there are pages to exclude
526
    if ( ! empty( $exclude_pages ) ) {
527
        $sql .= " AND ID NOT IN ($exclude_pages_placeholders)";
528
    }
529
530
    // Add sorting
531
    $sql .= " ORDER BY post_title ASC";
532
533
    // Add a sanity limit
534
    $limit = absint( apply_filters('wpinv_get_pages_limit',500) );
535
    $sql .= " LIMIT " . absint($limit);
536
537
    // Prepare the SQL query to include the excluded pages only if we have placeholders
538
    $pages = $exclude_pages_placeholders ? $wpdb->get_results( $wpdb->prepare( $sql, ...$exclude_pages ) ) : $wpdb->get_results( $sql );
539
540
	$pages_options = array();
541
542
    if ( $pages ) {
543
        foreach ( $pages as $page ) {
544
            $title = $with_slug ? $page->post_title . ' (' . $page->post_name . ')' : $page->post_title;
545
            $pages_options[ $page->ID ] = $title;
546
        }
547
    }
548
549
550
551
    $gp_tmpl_page_options = $pages_options;
552
553
    if ( $default_label !== null && $default_label !== false ) {
554
        $pages_options = array( '' => $default_label ) + $pages_options; // Blank option
555
    }
556
557
	return $pages_options;
558
}
559
560
function wpinv_header_callback( $args ) {
561
	if ( ! empty( $args['desc'] ) ) {
562
        echo wp_kses_post( $args['desc'] );
563
    }
564
}
565
566
function wpinv_hidden_callback( $args ) {
567
568
	$std     = isset( $args['std'] ) ? $args['std'] : '';
569
	$value   = wpinv_get_option( $args['id'], $std );
570
571
	if ( isset( $args['set_value'] ) ) {
572
		$value = $args['set_value'];
573
	}
574
575
	if ( isset( $args['faux'] ) && true === $args['faux'] ) {
576
		$args['readonly'] = true;
577
		$name  = '';
578
	} else {
579
		$name = 'wpinv_settings[' . esc_attr( $args['id'] ) . ']';
580
	}
581
582
	echo '<input type="hidden" id="wpinv_settings[' . esc_attr( $args['id'] ) . ']" name="' . esc_attr( $name ) . '" value="' . esc_attr( stripslashes( $value ) ) . '" />';
583
584
}
585
586
/**
587
 * Displays a checkbox settings callback.
588
 */
589
function wpinv_checkbox_callback( $args ) {
590
591
	$std = isset( $args['std'] ) ? $args['std'] : '';
592
	$std = wpinv_get_option( $args['id'], $std );
593
	$id  = esc_attr( $args['id'] );
594
595
	getpaid_hidden_field( "wpinv_settings[$id]", '0' );
596
	?>
597
		<label>
598
			<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" />
599
			<?php echo wp_kses_post( $args['desc'] ); ?>
600
		</label>
601
	<?php
602
}
603
604
function wpinv_multicheck_callback( $args ) {
605
606
	$sanitize_id = wpinv_sanitize_key( $args['id'] );
607
	$class = ! empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
608
609
	if ( ! empty( $args['options'] ) ) {
610
611
		$std     = isset( $args['std'] ) ? $args['std'] : array();
612
		$value   = wpinv_get_option( $args['id'], $std );
613
614
		echo '<div class="wpi-mcheck-rows wpi-mcheck-' . esc_attr( $sanitize_id . $class ) . '">';
615
        foreach ( $args['options'] as $key => $option ) :
616
			$sanitize_key = esc_attr( wpinv_sanitize_key( $key ) );
617
			if ( in_array( $sanitize_key, $value ) ) {
618
				$enabled = $sanitize_key;
619
			} else {
620
				$enabled = null;
621
			}
622
			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;';
623
			echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . '][' . esc_attr( $sanitize_key ) . ']">' . wp_kses_post( $option ) . '</label></div>';
624
		endforeach;
625
		echo '</div>';
626
		echo '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
627
	}
628
}
629
630
function wpinv_payment_icons_callback( $args ) {
631
632
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
633
	$value   = wpinv_get_option( $args['id'], false );
634
635
	if ( ! empty( $args['options'] ) ) {
636
		foreach ( $args['options'] as $key => $option ) {
637
            $sanitize_key = wpinv_sanitize_key( $key );
638
639
			if ( empty( $value ) ) {
640
				$enabled = $option;
641
			} else {
642
				$enabled = null;
643
			}
644
645
			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;">';
646
647
				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;';
648
649
				if ( wpinv_string_is_image_url( $key ) ) {
650
				echo '<img class="payment-icon" src="' . esc_url( $key ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
651
				} else {
652
				$card = strtolower( str_replace( ' ', '', $option ) );
653
654
				if ( has_filter( 'wpinv_accepted_payment_' . $card . '_image' ) ) {
655
					$image = apply_filters( 'wpinv_accepted_payment_' . $card . '_image', '' );
656
					} else {
657
					$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

657
					$image       = wpinv_locate_template( 'images' . DIRECTORY_SEPARATOR . 'icons' . DIRECTORY_SEPARATOR . $card . '.gif', /** @scrutinizer ignore-type */ false );
Loading history...
658
					$content_dir = WP_CONTENT_DIR;
659
660
					if ( function_exists( 'wp_normalize_path' ) ) {
661
						// Replaces backslashes with forward slashes for Windows systems
662
						$image = wp_normalize_path( $image );
663
						$content_dir = wp_normalize_path( $content_dir );
664
						}
665
666
					$image = str_replace( $content_dir, content_url(), $image );
667
					}
668
669
				echo '<img class="payment-icon" src="' . esc_url( $image ) . '" style="width:32px;height:24px;position:relative;top:6px;margin-right:5px;"/>';
670
				}
671
			echo wp_kses_post( $option ) . '</label>';
672
		}
673
		echo '<p class="description" style="margin-top:16px;">' . wp_kses_post( $args['desc'] ) . '</p>';
674
	}
675
}
676
677
/**
678
 * Displays a radio settings field.
679
 */
680
function wpinv_radio_callback( $args ) {
681
682
	$std = isset( $args['std'] ) ? $args['std'] : '';
683
	$std = wpinv_get_option( $args['id'], $std );
684
	?>
685
		<fieldset>
686
			<ul id="wpinv-settings-<?php echo esc_attr( $args['id'] ); ?>" style="margin-top: 0;">
687
				<?php foreach ( $args['options'] as $key => $option ) : ?>
688
					<li>
689
						<label>
690
							<input name="wpinv_settings[<?php echo esc_attr( $args['id'] ); ?>]" <?php checked( $std, $key ); ?> value="<?php echo esc_attr( $key ); ?>" type="radio">
691
							<?php echo wp_kses_post( $option ); ?>
692
						</label>
693
					</li>
694
				<?php endforeach; ?>
695
			</ul>
696
		</fieldset>
697
	<?php
698
	getpaid_settings_description_callback( $args );
699
}
700
701
/**
702
 * Displays a description if available.
703
 */
704
function getpaid_settings_description_callback( $args ) {
705
706
	if ( ! empty( $args['desc'] ) ) {
707
		$description = $args['desc'];
708
		echo wp_kses_post( "<p class='description'>$description</p>" );
709
	}
710
711
}
712
713
/**
714
 * Displays a list of available gateways.
715
 */
716
function wpinv_gateways_callback() {
717
718
	?>
719
		</td>
720
	</tr>
721
	<tr class="bsui">
722
    	<td colspan="2" class="p-0">
723
			<?php include plugin_dir_path( __FILE__ ) . 'views/html-gateways-edit.php'; ?>
724
725
	<?php
726
}
727
728
function wpinv_gateway_select_callback( $args ) {
729
730
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
731
    $class = ! empty( $args['class'] ) ? ' ' . esc_attr( $args['class'] ) : '';
732
	$std     = isset( $args['std'] ) ? $args['std'] : '';
733
	$value   = wpinv_get_option( $args['id'], $std );
734
735
	echo '<select name="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" class="' . esc_attr( $class ) . '" >';
736
737
	foreach ( $args['options'] as $key => $option ) :
738
739
		echo '<option value="' . esc_attr( $key ) . '" ';
740
741
		if ( isset( $args['selected'] ) && $args['selected'] !== null && $args['selected'] !== false ) {
742
            selected( $key, $args['selected'] );
743
        } else {
744
            selected( $key, $value );
745
        }
746
747
		echo '>' . esc_html( $option['admin_label'] ) . '</option>';
748
	endforeach;
749
750
	echo '</select>';
751
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
752
}
753
754
/**
755
 * Generates attributes.
756
 *
757
 * @param array $args
758
 * @return string
759
 */
760
function wpinv_settings_attrs_helper( $args ) {
761
762
	$value = isset( $args['std'] ) ? $args['std'] : '';
763
	$id    = esc_attr( $args['id'] );
764
	$value = is_scalar( $value ) ? $value : '';
765
766
	$attrs = array(
767
		'name'     => ! empty( $args['faux'] ) ? false : "wpinv_settings[$id]",
768
		'readonly' => ! empty( $args['faux'] ),
769
		'value'    => ! empty( $args['faux'] ) ? $value : wpinv_get_option( $args['id'], $value ),
770
		'id'       => 'wpinv-settings-' . $args['id'],
771
		'style'    => $args['style'],
772
		'class'    => $args['class'],
773
		'placeholder' => $args['placeholder'],
774
		'data-placeholder' => $args['placeholder'],
775
	);
776
777
	if ( ! empty( $args['onchange'] ) ) {
778
		$attrs['onchange'] = $args['onchange'];
779
	}
780
781
	foreach ( $attrs as $key => $value ) {
782
783
		if ( false === $value ) {
784
			continue;
785
		}
786
787
		if ( true === $value ) {
788
			echo ' ' . esc_attr( $key );
789
		} else {
790
			echo ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
791
		}
792
793
	}
794
795
}
796
797
/**
798
 * Displays a text input settings callback.
799
 */
800
function wpinv_text_callback( $args ) {
801
802
	?>
803
		<label style="width: 100%;">
804
			<input type="text" <?php wpinv_settings_attrs_helper( $args ); ?>>
805
			<?php getpaid_settings_description_callback( $args ); ?>
806
		</label>
807
	<?php
808
809
}
810
811
/**
812
 * Displays a number input settings callback.
813
 */
814
function wpinv_number_callback( $args ) {
815
816
	?>
817
		<label style="width: 100%;">
818
			<input type="number" step="<?php echo esc_attr( $args['step'] ); ?>" max="<?php echo intval( $args['max'] ); ?>" min="<?php echo intval( $args['min'] ); ?>" <?php wpinv_settings_attrs_helper( $args ); ?>>
819
			<?php getpaid_settings_description_callback( $args ); ?>
820
		</label>
821
	<?php
822
823
}
824
825
function wpinv_textarea_callback( $args ) {
826
827
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
828
	$std     = isset( $args['std'] ) ? $args['std'] : '';
829
	$value   = wpinv_get_option( $args['id'], $std );
830
831
    $size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
832
    $class = ( isset( $args['class'] ) && ! is_null( $args['class'] ) ) ? $args['class'] : 'large-text';
833
834
	echo '<textarea class="' . esc_attr( $class ) . ' txtarea-' . esc_attr( $size ) . ' wpi-' . esc_attr( sanitize_html_class( $sanitize_id ) ) . ' " cols="' . esc_attr( $args['cols'] ) . '" rows="' . esc_attr( $args['rows'] ) . '" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
835
	echo '<br /><label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
836
837
}
838
839
function wpinv_password_callback( $args ) {
840
841
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
842
	$std     = isset( $args['std'] ) ? $args['std'] : '';
843
	$value   = wpinv_get_option( $args['id'], $std );
844
845
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
846
	echo '<input type="password" class="' . esc_attr( $size ) . '-text" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( $value ) . '"/>';
847
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
848
849
}
850
851
function wpinv_missing_callback( $args ) {
852
	printf(
853
		esc_html__( 'The callback function used for the %s setting is missing.', 'invoicing' ),
854
		'<strong>' . esc_html( $args['id'] ) . '</strong>'
855
	);
856
}
857
858
/**
859
 * Displays a number input settings callback.
860
 */
861
function wpinv_select_callback( $args ) {
862
863
	$desc   = wp_kses_post( $args['desc'] );
864
	$desc   = empty( $desc ) ? '' : "<p class='description'>$desc</p>";
865
	$value  = isset( $args['std'] ) ? $args['std'] : '';
866
	$value  = wpinv_get_option( $args['id'], $value );
867
	$rand   = uniqid( 'random_id' );
868
869
	?>
870
		<label style="width: 100%;">
871
			<select <?php wpinv_settings_attrs_helper( $args ); ?> data-allow-clear="true">
872
				<?php foreach ( $args['options'] as $option => $name ) : ?>
873
					<option value="<?php echo esc_attr( $option ); ?>" <?php echo selected( $option, $value ); ?>><?php echo esc_html( $name ); ?></option>
874
				<?php endforeach; ?>
875
			</select>
876
877
			<?php if ( substr( $args['id'], -5 ) === '_page' && is_numeric( $value ) ) : ?>
878
				<a href="<?php echo esc_url( 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 $post 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

878
				<a href="<?php echo esc_url( 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...
879
			<?php endif; ?>
880
881
			<?php if ( substr( $args['id'], -5 ) === '_page' && ! empty( $args['default_content'] ) ) : ?>
882
				&nbsp;<a href="#TB_inline?&width=400&height=550&inlineId=<?php echo esc_attr( $rand ); ?>" class="button thickbox getpaid-page-setting-view-default"><?php esc_html_e( 'View Default Content', 'invoicing' ); ?></a>
883
				<div id='<?php echo esc_attr( $rand ); ?>' style='display:none;'>
884
					<div>
885
						<h3><?php esc_html_e( 'Original Content', 'invoicing' ); ?></h3>
886
						<textarea readonly onclick="this.select()" rows="8" style="width: 100%;"><?php echo wp_kses_post( gepaid_trim_lines( $args['default_content'] ) ); ?></textarea>
887
						<h3><?php esc_html_e( 'Current Content', 'invoicing' ); ?></h3>
888
						<textarea readonly onclick="this.select()" rows="8" style="width: 100%;"><?php $_post = get_post( $value ); echo empty( $_post ) ? '' : wp_kses_post( gepaid_trim_lines( $_post->post_content ) ); ?></textarea>
889
					</div>
890
				</div>
891
			<?php endif; ?>
892
893
			<?php echo wp_kses_post( $desc ); ?>
894
		</label>
895
	<?php
896
897
}
898
899
function wpinv_color_select_callback( $args ) {
900
901
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
902
	$std     = isset( $args['std'] ) ? $args['std'] : '';
903
	$value   = wpinv_get_option( $args['id'], $std );
904
905
	echo '<select id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']"/>';
906
907
	foreach ( $args['options'] as $option => $color ) {
908
		echo '<option value="' . esc_attr( $option ) . '" ' . selected( $option, $value ) . '>' . esc_html( $color['label'] ) . '</option>';
909
	}
910
911
	echo '</select>';
912
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
913
914
}
915
916
function wpinv_rich_editor_callback( $args ) {
917
	global $wp_version;
918
919
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
920
921
	$std     = isset( $args['std'] ) ? $args['std'] : '';
922
	$value   = wpinv_get_option( $args['id'], $std );
923
924
	if ( ! empty( $args['allow_blank'] ) && empty( $value ) ) {
925
		$value = $std;
926
	}
927
928
	$rows = isset( $args['size'] ) ? $args['size'] : 20;
929
930
	echo '<div class="getpaid-settings-editor-input">';
931
	if ( $wp_version >= 3.3 && function_exists( 'wp_editor' ) ) {
932
		wp_editor(
933
            stripslashes( $value ),
934
            'wpinv_settings_' . esc_attr( $args['id'] ),
935
            array(
936
				'textarea_name' => 'wpinv_settings[' . esc_attr( $args['id'] ) . ']',
937
				'textarea_rows' => absint( $rows ),
938
				'media_buttons' => false,
939
            )
940
        );
941
	} else {
942
		echo '<textarea class="large-text" rows="10" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" class="wpi-' . esc_attr( sanitize_html_class( $args['id'] ) ) . '">' . esc_textarea( stripslashes( $value ) ) . '</textarea>';
943
	}
944
945
	echo '</div><br/><label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
946
947
}
948
949
function wpinv_upload_callback( $args ) {
950
951
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
952
953
	$std     = isset( $args['std'] ) ? $args['std'] : '';
954
	$value   = wpinv_get_option( $args['id'], $std );
955
956
	$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
957
	echo '<input type="text" class="' . sanitize_html_class( $size ) . '-text" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( stripslashes( $value ) ) . '"/>';
958
	echo '<span>&nbsp;<input type="button" class="wpinv_settings_upload_button button-secondary" value="' . esc_attr__( 'Upload File', 'invoicing' ) . '"/></span>';
959
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
960
961
}
962
963
function wpinv_color_callback( $args ) {
964
965
	$std         = isset( $args['std'] ) ? $args['std'] : '';
966
	$value       = wpinv_get_option( $args['id'], $std );
967
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
968
969
	echo '<input type="text" class="wpinv-color-picker" id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" value="' . esc_attr( $value ) . '" data-default-color="' . esc_attr( $std ) . '" />';
970
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
971
972
}
973
974
function wpinv_country_states_callback( $args ) {
975
976
	$std     = isset( $args['std'] ) ? $args['std'] : '';
977
	$value   = wpinv_get_option( $args['id'], $std );
978
979
    $sanitize_id = wpinv_sanitize_key( $args['id'] );
980
981
	if ( isset( $args['placeholder'] ) ) {
982
		$placeholder = $args['placeholder'];
983
	} else {
984
		$placeholder = '';
985
	}
986
987
	$states = wpinv_get_country_states();
988
989
	$class = empty( $states ) ? 'wpinv-no-states' : 'wpi_select2';
990
	echo '<select id="wpinv_settings[' . esc_attr( $sanitize_id ) . ']" name="wpinv_settings[' . esc_attr( $args['id'] ) . ']" class="' . esc_attr( $class ) . '" data-placeholder="' . esc_html( $placeholder ) . '"/>';
991
992
	foreach ( $states as $option => $name ) {
993
		echo '<option value="' . esc_attr( $option ) . '" ' . selected( $option, $value ) . '>' . esc_html( $name ) . '</option>';
994
	}
995
996
	echo '</select>';
997
	echo '<label for="wpinv_settings[' . esc_attr( $sanitize_id ) . ']"> ' . wp_kses_post( $args['desc'] ) . '</label>';
998
999
}
1000
1001
/**
1002
 * Displays the tax rates edit table.
1003
 */
1004
function wpinv_tax_rates_callback() {
1005
1006
	?>
1007
		</td>
1008
	</tr>
1009
	<tr class="bsui">
1010
    	<td colspan="2" class="p-0">
1011
			<?php include plugin_dir_path( __FILE__ ) . 'views/html-tax-rates-edit.php'; ?>
1012
1013
	<?php
1014
1015
}
1016
1017
/**
1018
 * Displays a tax rate' edit row.
1019
 */
1020
function wpinv_tax_rate_callback( $tax_rate, $key ) {
1021
1022
	$key                      = sanitize_key( $key );
1023
	$tax_rate['reduced_rate'] = empty( $tax_rate['reduced_rate'] ) ? 0 : $tax_rate['reduced_rate'];
1024
	include plugin_dir_path( __FILE__ ) . 'views/html-tax-rate-edit.php';
1025
1026
}
1027
1028
/**
1029
 * Displays the tax rules edit table.
1030
 */
1031
function wpinv_tax_rules_callback() {
1032
1033
	?>
1034
		</td>
1035
	</tr>
1036
	<tr class="bsui">
1037
    	<td colspan="2" class="p-0">
1038
			<?php include plugin_dir_path( __FILE__ ) . 'views/html-tax-rules-edit.php'; ?>
1039
1040
	<?php
1041
1042
}
1043
1044
function wpinv_tools_callback( $args ) {
1045
    ?>
1046
    </td><tr>
1047
    <td colspan="2" class="wpinv_tools_tdbox">
1048
    <?php
1049
    if ( $args['desc'] ) {
1050
?>
1051
<p><?php echo wp_kses_post( $args['desc'] ); ?></p><?php } ?>
1052
    <?php do_action( 'wpinv_tools_before' ); ?>
1053
    <table id="wpinv_tools_table" class="wp-list-table widefat fixed posts">
1054
        <thead>
1055
            <tr>
1056
                <th scope="col" class="wpinv-th-tool"><?php esc_html_e( 'Tool', 'invoicing' ); ?></th>
1057
                <th scope="col" class="wpinv-th-desc"><?php esc_html_e( 'Description', 'invoicing' ); ?></th>
1058
                <th scope="col" class="wpinv-th-action"><?php esc_html_e( 'Action', 'invoicing' ); ?></th>
1059
            </tr>
1060
        </thead>
1061
1062
        <tbody>
1063
			<tr>
1064
                <td><?php esc_html_e( 'Check Pages', 'invoicing' ); ?></td>
1065
                <td>
1066
                    <small><?php esc_html_e( 'Creates any missing GetPaid pages.', 'invoicing' ); ?></small>
1067
                </td>
1068
                <td>
1069
					<a href="
1070
                    <?php
1071
						echo esc_url(
1072
							wp_nonce_url(
1073
								add_query_arg( 'getpaid-admin-action', 'create_missing_pages' ),
1074
								'getpaid-nonce',
1075
								'getpaid-nonce'
1076
							)
1077
						);
1078
					?>
1079
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1080
                </td>
1081
            </tr>
1082
			<tr>
1083
                <td><?php esc_html_e( 'Refresh Permalinks', 'invoicing' ); ?></td>
1084
                <td>
1085
                    <small><?php esc_html_e( 'Might fix the page not found error when viewing an invoice.', 'invoicing' ); ?></small>
1086
                </td>
1087
                <td>
1088
					<a href="
1089
                    <?php
1090
						echo esc_url(
1091
							wp_nonce_url(
1092
								add_query_arg( 'getpaid-admin-action', 'refresh_permalinks' ),
1093
								'getpaid-nonce',
1094
								'getpaid-nonce'
1095
							)
1096
						);
1097
					?>
1098
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1099
                </td>
1100
            </tr>
1101
			<tr>
1102
                <td><?php esc_html_e( 'Repair Database Tables', 'invoicing' ); ?></td>
1103
                <td>
1104
                    <small><?php esc_html_e( 'Run this tool to create any missing database tables.', 'invoicing' ); ?></small>
1105
                </td>
1106
                <td>
1107
					<a href="
1108
                    <?php
1109
						echo esc_url(
1110
							wp_nonce_url(
1111
								add_query_arg( 'getpaid-admin-action', 'create_missing_tables' ),
1112
								'getpaid-nonce',
1113
								'getpaid-nonce'
1114
							)
1115
						);
1116
					?>
1117
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1118
                </td>
1119
            </tr>
1120
			<tr>
1121
                <td><?php esc_html_e( 'Migrate old invoices', 'invoicing' ); ?></td>
1122
                <td>
1123
                    <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>
1124
                </td>
1125
                <td>
1126
					<a href="
1127
                    <?php
1128
						echo esc_url(
1129
							wp_nonce_url(
1130
								add_query_arg( 'getpaid-admin-action', 'migrate_old_invoices' ),
1131
								'getpaid-nonce',
1132
								'getpaid-nonce'
1133
							)
1134
						);
1135
					?>
1136
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1137
                </td>
1138
            </tr>
1139
1140
			<tr>
1141
                <td><?php esc_html_e( 'Recalculate Discounts', 'invoicing' ); ?></td>
1142
                <td>
1143
                    <small><?php esc_html_e( 'Recalculate discounts for existing invoices that have discount codes but are not discounted.', 'invoicing' ); ?></small>
1144
                </td>
1145
                <td>
1146
					<a href="
1147
                    <?php
1148
						echo esc_url(
1149
							wp_nonce_url(
1150
								add_query_arg( 'getpaid-admin-action', 'recalculate_discounts' ),
1151
								'getpaid-nonce',
1152
								'getpaid-nonce'
1153
							)
1154
						);
1155
					?>
1156
                    " class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1157
                </td>
1158
            </tr>
1159
1160
			<tr>
1161
				<td><?php esc_html_e( 'Database Text Translation', 'invoicing' ); ?></td>
1162
				<td>
1163
					<small><?php esc_html_e( 'This tool will collect any strings stored in the database and put them in the file db-language.php, so those strings can be used to translate by translation tools.', 'invoicing' ); ?></small>
1164
				</td>
1165
				<td>
1166
					<a href=" <?php echo esc_url( wp_nonce_url( add_query_arg( 'getpaid-admin-action', 'translate_db_texts' ), 'getpaid-nonce', 'getpaid-nonce' ) ); ?>" class="button button-primary"><?php esc_html_e( 'Run', 'invoicing' ); ?></a>
1167
				</td>
1168
			</tr>
1169
1170
			<tr>
1171
                <td><?php esc_html_e( 'Set-up Wizard', 'invoicing' ); ?></td>
1172
                <td>
1173
                    <small><?php esc_html_e( 'Launch the quick set-up wizard.', 'invoicing' ); ?></small>
1174
                </td>
1175
                <td>
1176
					<a href="
1177
                    <?php
1178
						echo esc_url( admin_url( 'index.php?page=gp-setup' ) );
1179
					?>
1180
                    " class="button button-primary"><?php esc_html_e( 'Launch', 'invoicing' ); ?></a>
1181
                </td>
1182
            </tr>
1183
1184
			<?php do_action( 'wpinv_tools_row' ); ?>
1185
        </tbody>
1186
    </table>
1187
    <?php do_action( 'wpinv_tools_after' ); ?>
1188
    <?php
1189
}
1190
1191
1192
function wpinv_descriptive_text_callback( $args ) {
1193
	echo wp_kses_post( $args['desc'] );
1194
}
1195
1196
function wpinv_raw_html_callback( $args ) {
1197
	echo wp_kses( $args['desc'], getpaid_allowed_html() );
1198
}
1199
1200
function wpinv_hook_callback( $args ) {
1201
	do_action( 'wpinv_' . $args['id'], $args );
1202
}
1203
1204
function wpinv_set_settings_cap() {
1205
	return wpinv_get_capability();
1206
}
1207
add_filter( 'option_page_capability_wpinv_settings', 'wpinv_set_settings_cap' );
1208
1209
1210
function wpinv_on_update_settings( $old_value, $value, $option ) {
1211
    $old = ! empty( $old_value['remove_data_on_unistall'] ) ? 1 : '';
1212
    $new = ! empty( $value['remove_data_on_unistall'] ) ? 1 : '';
1213
1214
    if ( $old != $new ) {
1215
        update_option( 'wpinv_remove_data_on_invoice_unistall', $new );
1216
    }
1217
}
1218
add_action( 'update_option_wpinv_settings', 'wpinv_on_update_settings', 10, 3 );
1219
1220
1221
/**
1222
 * Retrieve merge tags for email templates.
1223
 * 
1224
 * Returns an array of merge tags that can be used in email templates for invoices & subscriptions.
1225
 * 
1226
 * @since    2.1.8
1227
 *
1228
 * @return array
1229
 */
1230
function wpinv_get_email_merge_tags( $subscription = false ) {
1231
	$merge_tags = array(
1232
		'{site_title}'           => __( 'Site Title', 'invoicing' ),
1233
		'{name}'                 => __( "Customer's full name", 'invoicing' ),
1234
		'{first_name}'           => __( "Customer's first name", 'invoicing' ),
1235
		'{last_name}'            => __( "Customer's last name", 'invoicing' ),
1236
		'{email}'                => __( "Customer's email address", 'invoicing' ),
1237
		'{invoice_number}'       => __( 'The invoice number', 'invoicing' ),
1238
		'{invoice_currency}'     => __( 'The invoice currency', 'invoicing' ),
1239
		'{invoice_total}'        => __( 'The invoice total', 'invoicing' ),
1240
		'{invoice_link}'         => __( 'The invoice link', 'invoicing' ),
1241
		'{invoice_pay_link}'     => __( 'The payment link', 'invoicing' ),
1242
		'{invoice_receipt_link}' => __( 'The receipt link', 'invoicing' ),
1243
		'{invoice_date}'         => __( 'The date the invoice was created', 'invoicing' ),
1244
		'{invoice_due_date}'     => __( 'The date the invoice is due', 'invoicing' ),
1245
		'{date}'                 => __( "Today's date", 'invoicing' ),
1246
		'{is_was}'               => __( 'If due date of invoice is past, displays "was" otherwise displays "is"', 'invoicing' ),
1247
		'{invoice_label}'        => __( 'Invoices/quotes singular name. Ex: Invoice/Quote', 'invoicing' ),
1248
		'{invoice_quote}'        => __( 'Invoices/quotes singular name in small letters. Ex: invoice/quote', 'invoicing' ),
1249
		'{invoice_description}'  => __( 'The description of the invoice', 'invoicing' ),
1250
	);
1251
1252
	if ( $subscription ) {
1253
		$merge_tags = array_merge(
1254
			$merge_tags,
1255
			array(
1256
				'{subscription_renewal_date}'     => __( 'The next renewal date of the subscription', 'invoicing' ),
1257
				'{subscription_created}'          => __( "The subscription's creation date", 'invoicing' ),
1258
				'{subscription_status}'           => __( "The subscription's status", 'invoicing' ),
1259
				'{subscription_profile_id}'       => __( "The subscription's remote profile id", 'invoicing' ),
1260
				'{subscription_id}'               => __( "The subscription's id", 'invoicing' ),
1261
				'{subscription_recurring_amount}' => __( 'The renewal amount of the subscription', 'invoicing' ),
1262
				'{subscription_initial_amount}'   => __( 'The initial amount of the subscription', 'invoicing' ),
1263
				'{subscription_recurring_period}' => __( 'The recurring period of the subscription (e.g 1 year)', 'invoicing' ),
1264
				'{subscription_bill_times}'       => __( 'The maximum number of times the subscription can be renewed', 'invoicing' ),
1265
				'{subscription_url}'              => __( 'The URL to manage a subscription', 'invoicing' ),
1266
				'{subscription_name}'             => __( 'The name of the recurring item', 'invoicing' ),
1267
			)
1268
		);
1269
	}
1270
1271
	return $merge_tags;
1272
}
1273
1274
1275
/**
1276
 * Returns the merge tags help text.
1277
 *
1278
 * @since    2.1.8
1279
 *
1280
 * @return string
1281
 */
1282
function wpinv_get_merge_tags_help_text( $subscription = false ) {
1283
	$merge_tags = wpinv_get_email_merge_tags( $subscription );
1284
1285
	$output = '<div class="bsui">';
1286
1287
	$link = sprintf(
1288
		'<strong class="getpaid-merge-tags text-primary" role="button">%s</strong>',
1289
		esc_html__( 'View available merge tags.', 'invoicing' )
1290
	);
1291
1292
	$description = esc_html__( 'The content of the email (Merge Tags and HTML are allowed).', 'invoicing' );
1293
	
1294
	$output .= "$description $link";
1295
1296
	$output .= '<div class="getpaid-merge-tags-content mt-2 p-1 d-none">';
1297
	$output .= '<p class="mb-2">' . esc_html__( 'The following wildcards can be used in email subjects, heading and content:', 'invoicing' ) . '</p>';
1298
1299
	$output .= '<ul class="p-0 m-0">';
1300
	foreach($merge_tags as $tag => $tag_description) {
1301
		$output .= "<li class='mb-2'><strong class='text-dark'>$tag</strong> &mdash; $tag_description</li>";
1302
	}
1303
1304
	$output .= '</ul></div></div>';
1305
1306
	return $output;
1307
}
1308