Issues (896)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/class-sensei-settings-api.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
/**
5
 * A settings API (wrapping the WordPress Settings API).
6
 *
7
 * @package Core
8
 * @author Automattic
9
 *
10
 * @since 1.0.0
11
 */
12
class Sensei_Settings_API {
13
14
	public $token;
15
	public $page_slug;
16
	public $name;
17
	public $menu_label;
18
	public $settings;
19
	public $sections;
20
	public $fields;
21
	public $errors;
22
23
	public $has_range;
24
	public $has_imageselector;
25
	public $has_tabs;
26
	private $tabs;
27
	public $settings_version;
28
29
	/**
30
	 * Constructor.
31
	 * @access public
32
	 * @since  1.0.0
33
	 */
34
	public function __construct () {
35
36
		$this->token = 'woothemes-sensei-settings';
37
		$this->page_slug = 'woothemes-sensei-settings-api';
38
39
		$this->sections = array();
40
		$this->fields = array();
41
		$this->remaining_fields = array();
42
		$this->errors = array();
43
44
		$this->has_range = false;
45
		$this->has_imageselector = false;
46
		$this->has_tabs = false;
47
		$this->tabs = array();
48
		$this->settings_version = '';
49
50
	} // End __construct()
51
52
	/**
53
	 * Setup the settings screen and necessary functions.
54
	 * @access public
55
	 * @since  1.0.0
56
	 * @return void
57
	 */
58
	public function register_hook_listener() {
59
60
        add_action( 'admin_menu', array( $this, 'register_settings_screen' ), 60 );
61
		add_action( 'admin_init', array( $this, 'settings_fields' ) );
62
        add_action( 'init', array( $this, 'general_init' ), 5 );
63
64
	} // End setup_settings()
65
66
	/**
67
	 * Initialise settings sections, settings fields and create tabs, if applicable.
68
	 * @access  public
69
	 * @since   1.0.3
70
	 * @return  void
71
	 */
72
	public function general_init() {
73
		$this->init_sections();
74
		$this->init_fields();
75
		$this->get_settings();
76
		if ( $this->has_tabs == true ) {
77
			$this->create_tabs();
78
		} // End If Statement
79
	} // End general_init()
80
81
	/**
82
	 * Register the settings sections.
83
	 * @access public
84
	 * @since  1.0.0
85
	 * @return void
86
	 */
87
	public function init_sections () {
88
		// Override this function in your class and assign the array of sections to $this->sections.
89
		_e( 'Override init_sections() in your class.', 'woothemes-sensei' );
90
	} // End init_sections()
91
92
	/**
93
	 * Register the settings fields.
94
	 * @access public
95
	 * @since  1.0.0
96
	 * @return void
97
	 */
98
	public function init_fields () {
99
		// Override this function in your class and assign the array of sections to $this->fields.
100
		_e( 'Override init_fields() in your class.', 'woothemes-sensei' );
101
	} // End init_fields()
102
103
	/**
104
	 * Construct and output HTML markup for the settings tabs.
105
	 * @access public
106
	 * @since  1.1.0
107
	 * @return void
108
	 */
109
	public function settings_tabs () {
110
111
		if ( ! $this->has_tabs ) { return; }
112
113
		if ( count( $this->tabs ) > 0 ) {
114
			$html = '';
115
116
			$html .= '<ul id="settings-sections" class="subsubsub hide-if-no-js">' . "\n";
117
118
			$sections = array(
119
						'all' => array( 'href' => '#all', 'name' => __( 'All', 'woothemes-sensei' ), 'class' => 'current all tab' )
120
					);
121
122
			foreach ( $this->tabs as $k => $v ) {
123
				$sections[$k] = array( 'href' => '#' . esc_attr( $k ), 'name' => esc_attr( $v['name'] ), 'class' => 'tab' );
124
			}
125
126
			$count = 1;
127
			foreach ( $sections as $k => $v ) {
128
				$count++;
129
				$html .= '<li><a href="' . $v['href'] . '"';
130 View Code Duplication
				if ( isset( $v['class'] ) && ( $v['class'] != '' ) ) { $html .= ' class="' . esc_attr( $v['class'] ) . '"'; }
131
				$html .= '>' . esc_attr( $v['name'] ) . '</a>';
132
				if ( $count <= count( $sections ) ) { $html .= ' | '; }
133
				$html .= '</li>' . "\n";
134
			}
135
136
			$html .= '</ul><div class="clear"></div>' . "\n";
137
138
			echo $html;
139
		}
140
	} // End settings_tabs()
141
142
	/**
143
	 * Create settings tabs based on the settings sections.
144
	 * @access private
145
	 * @since  1.1.0
146
	 * @return void
147
	 */
148
	private function create_tabs () {
149
		if ( count( $this->sections ) > 0 ) {
150
			$tabs = array();
151
			foreach ( $this->sections as $k => $v ) {
152
				$tabs[$k] = $v;
153
			}
154
155
			$this->tabs = $tabs;
156
		}
157
	} // End create_tabs()
158
159
	/**
160
	 * Create settings sections.
161
	 * @access public
162
	 * @since  1.0.0
163
	 * @return void
164
	 */
165
	public function create_sections () {
166
		if ( count( $this->sections ) > 0 ) {
167
			foreach ( $this->sections as $k => $v ) {
168
				add_settings_section( $k, $v['name'], array( $this, 'section_description' ), $this->token );
169
			}
170
		}
171
	} // End create_sections()
172
173
	/**
174
	 * Create settings fields.
175
	 * @access public
176
	 * @since  1.0.0
177
	 * @return void
178
	 */
179
	public function create_fields () {
180
		if ( count( $this->sections ) > 0 ) {
181
			// $this->parse_fields( $this->fields );
182
183
			foreach ( $this->fields as $k => $v ) {
184
				$method = $this->determine_method( $v, 'form' );
185
				$name = $v['name'];
186
				if ( $v['type'] == 'info' ) { $name = ''; }
187
				add_settings_field( $k, $name, $method, $this->token, $v['section'], array( 'key' => $k, 'data' => $v ) );
188
189
				// Let the API know that we have a colourpicker field.
190
				if ( $v['type'] == 'range' && $this->has_range == false ) { $this->has_range = true; }
191
			}
192
		}
193
	} // End create_fields()
194
195
	/**
196
	 * Determine the method to use for outputting a field, validating a field or checking a field.
197
	 * @access protected
198
	 * @since  1.0.0
199
	 * @param  array $data
200
	 * @return callable,  array or string
0 ignored issues
show
The doc-type callable, could not be parsed: Expected "|" or "end of type", but got "," at position 8. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
201
	 */
202
	protected function determine_method ( $data, $type = 'form' ) {
203
		$method = '';
204
205
		if ( ! in_array( $type, array( 'form', 'validate', 'check' ) ) ) { return; }
206
207
		// Check for custom functions.
208
		if ( isset( $data[$type] ) ) {
209
			if ( function_exists( $data[$type] ) ) {
210
				$method = $data[$type];
211
			}
212
213
			if ( $method == '' && method_exists( $this, $data[$type] ) ) {
214
				if ( $type == 'form' ) {
215
					$method = array( $this, $data[$type] );
216
				} else {
217
					$method = $data[$type];
218
				}
219
			}
220
		}
221
222
		if ( $method == '' && method_exists ( $this, $type . '_field_' . $data['type'] ) ) {
223
			if ( $type == 'form' ) {
224
				$method = array( $this, $type . '_field_' . $data['type'] );
225
			} else {
226
				$method = $type . '_field_' . $data['type'];
227
			}
228
		}
229
230
		if ( $method == '' && function_exists ( $this->token . '_' . $type . '_field_' . $data['type'] ) ) {
231
			$method = $this->token . '_' . $type . '_field_' . $data['type'];
232
		}
233
234
		if ( $method == '' ) {
235
			if ( $type == 'form' ) {
236
				$method = array( $this, $type . '_field_text' );
237
			} else {
238
				$method = $type . '_field_text';
239
			}
240
		}
241
242
		return $method;
243
	} // End determine_method()
244
245
	/**
246
	 * Parse the fields into an array index on the sections property.
247
	 * @access public
248
	 * @since  1.0.0
249
	 * @param  array $fields
250
	 * @return void
251
	 */
252
	public function parse_fields ( $fields ) {
253
		foreach ( $fields as $k => $v ) {
254
			if ( isset( $v['section'] ) && ( $v['section'] != '' ) && ( isset( $this->sections[$v['section']] ) ) ) {
255 View Code Duplication
				if ( ! isset( $this->sections[$v['section']]['fields'] ) ) {
256
					$this->sections[$v['section']]['fields'] = array();
257
				}
258
259
				$this->sections[$v['section']]['fields'][$k] = $v;
260
			} else {
261
				$this->remaining_fields[$k] = $v;
262
			}
263
		}
264
	} // End parse_fields()
265
266
	/**
267
	 * Register the settings screen within the WordPress admin.
268
	 * @access public
269
	 * @since 1.0.0
270
	 * @return void
271
	 */
272
	public function register_settings_screen () {
273
274 View Code Duplication
		if ( current_user_can( 'manage_sensei' ) ) {
275
			$hook = add_submenu_page( 'sensei', $this->name, $this->menu_label, 'manage_sensei', $this->page_slug, array( $this, 'settings_screen' ) );
276
277
			$this->hook = $hook;
278
		}
279
280
		if ( isset( $_GET['page'] ) && ( $_GET['page'] == $this->page_slug ) ) {
281
282
			add_action( 'admin_notices', array( $this, 'settings_errors' ) );
283
			add_action( 'admin_print_scripts', array( $this, 'enqueue_scripts' ) );
284
			add_action( 'admin_print_styles', array( $this, 'enqueue_styles' ) );
285
286
		}
287
	} // End register_settings_screen()
288
289
	/**
290
	 * The markup for the settings screen.
291
	 * @access public
292
	 * @since  1.0.0
293
	 * @return void
294
	 */
295
	public function settings_screen ()
296
    {
297
298
        ?>
299
        <div id="woothemes-sensei" class="wrap <?php echo esc_attr($this->token); ?>">
300
        <?php screen_icon('woothemes-sensei'); ?>
301
        <h2><?php echo esc_html($this->name); ?><?php if ('' != $this->settings_version) {
302
                echo ' <span class="version">' . $this->settings_version . '</span>';
303
            } ?></h2>
304
        <p class="powered-by-woo"><?php _e('Powered by', 'woothemes-sensei'); ?><a href="http://www.woothemes.com/"
305
                                                                                   title="WooThemes"><img
306
                    src="<?php echo Sensei()->plugin_url; ?>assets/images/woothemes.png" alt="WooThemes"/></a></p>
307
        <?php do_action('settings_before_form'); ?>
308
        <form action="options.php" method="post">
309
310
        <?php
311
        $this->settings_tabs();
312
        settings_fields($this->token);
313
        $page = 'woothemes-sensei-settings';
314
        foreach ($this->sections as $section_id => $section) {
315
316
            echo '<section id="' . $section_id . '">';
317
318
            if ($section['name'])
319
                echo "<h2>{$section['name']}</h2>\n";
320
321
            echo '<table class="form-table">';
322
            do_settings_fields($page, $section_id );
323
            echo '</table>';
324
325
            echo '</section>';
326
327
        }
328
329
        submit_button();
330
        ?>
331
	</form>
332
	<?php do_action( 'settings_after_form' ); ?>
333
</div><!--/#woothemes-sensei-->
334
<?php
335
	} // End settings_screen()
336
337
	/**
338
	 * Retrieve the settings from the database.
339
	 * @access public
340
	 * @since  1.0.0
341
	 * @return array
342
	 */
343
	public function get_settings () {
344
345
        $this->settings = get_option( $this->token, array() );
346
347
		foreach ( $this->fields as $k => $v ) {
348
			if ( ! isset( $this->settings[$k] ) && isset( $v['default'] ) ) {
349
				$this->settings[$k] = $v['default'];
350
			}
351
			if ( $v['type'] == 'checkbox' && $this->settings[$k] != true ) {
352
				$this->settings[$k] = 0;
353
			}
354
		}
355
356
		return $this->settings;
357
	} // End get_settings()
358
359
	/**
360
	 * Register the settings fields.
361
	 * @access public
362
	 * @since  1.0.0
363
	 * @return void
364
	 */
365
	public function settings_fields () {
366
		register_setting( $this->token, $this->token, array( $this, 'validate_fields' ) );
367
		$this->create_sections();
368
		$this->create_fields();
369
	} // End settings_fields()
370
371
	/**
372
	 * Display settings errors.
373
	 * @access public
374
	 * @since  1.0.0
375
	 * @return void
376
	 */
377
	public function settings_errors () {
378
        settings_errors( $this->token . '-errors' );
379
	} // End settings_errors()
380
381
	/**
382
	 * Display the description for a settings section.
383
	 * @access public
384
	 * @since  1.0.0
385
	 * @return void
386
	 */
387
	public function section_description ( $section ) {
388 View Code Duplication
		if ( isset( $this->sections[$section['id']]['description'] ) ) {
389
			echo wpautop( $this->sections[$section['id']]['description'] );
390
		}
391
	} // End section_description_main()
392
393
	/**
394
	 * Generate text input field.
395
	 * @access public
396
	 * @since  1.0.0
397
	 * @param  array $args
398
	 * @return void
399
	 */
400 View Code Duplication
	public function form_field_text ( $args ) {
401
		$options = $this->get_settings();
402
403
		echo '<input id="' . esc_attr( $args['key'] ) . '" name="' . $this->token . '[' . esc_attr( $args['key'] ) . ']" size="40" type="text" value="' . esc_attr( $options[$args['key']] ) . '" />' . "\n";
404
		if ( isset( $args['data']['description'] ) ) {
405
			echo '<span class="description">' . $args['data']['description'] . '</span>' . "\n";
406
		}
407
	} // End form_field_text()
408
409
	/**
410
	 * Generate color picker field.
411
	 * @access public
412
	 * @since  1.6.0
413
	 * @param  array $args
414
	 * @return void
415
	 */
416 View Code Duplication
	public function form_field_color ( $args ) {
417
		$options = $this->get_settings();
418
419
		echo '<input id="' . esc_attr( $args['key'] ) . '" name="' . $this->token . '[' . esc_attr( $args['key'] ) . ']" size="40" type="text" class="color" value="' . esc_attr( $options[$args['key']] ) . '" />' . "\n";
420
		echo '<div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>';
421
		if ( isset( $args['data']['description'] ) ) {
422
			echo '<span class="description">' . $args['data']['description'] . '</span>' . "\n";
423
		}
424
	} // End form_field_text()
425
426
	/**
427
	 * Generate checkbox field.
428
	 * @access public
429
	 * @since  1.0.0
430
	 * @param  array $args
431
	 * @return void
432
	 */
433
	public function form_field_checkbox ( $args ) {
434
		$options = $this->get_settings();
435
436
		$has_description = false;
437
		if ( isset( $args['data']['description'] ) ) {
438
			$has_description = true;
439
			echo '<label for="' . esc_attr( $args['key'] ) . '">' . "\n";
440
		}
441
		echo '<input id="' . $args['key'] . '" name="' . $this->token . '[' . esc_attr( $args['key'] ) . ']" type="checkbox" value="1"' . checked( esc_attr( $options[$args['key']] ), '1', false ) . ' />' . "\n";
442
		if ( $has_description ) {
443
			echo wp_kses( $args['data']['description'], array( 'a' => array(
444
																	        'href' => array(),
445
																	        'title' => array()
446
																	    )
447
															)
448
						) . '</label>' . "\n";
449
		}
450
	} // End form_field_checkbox()
451
452
	/**
453
	 * Generate textarea field.
454
	 * @access public
455
	 * @since  1.0.0
456
	 * @param  array $args
457
	 * @return void
458
	 */
459 View Code Duplication
	public function form_field_textarea ( $args ) {
460
		$options = $this->get_settings();
461
462
		echo '<textarea id="' . esc_attr( $args['key'] ) . '" name="' . $this->token . '[' . esc_attr( $args['key'] ) . ']" cols="42" rows="5">' . esc_html( $options[$args['key']] ) . '</textarea>' . "\n";
463
		if ( isset( $args['data']['description'] ) ) {
464
			echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
465
		}
466
	} // End form_field_textarea()
467
468
	/**
469
	 * Generate select box field.
470
	 * @access public
471
	 * @since  1.0.0
472
	 * @param  array $args
473
	 * @return void
474
	 */
475 View Code Duplication
	public function form_field_select ( $args ) {
476
		$options = $this->get_settings();
477
478
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
479
			$html = '';
480
			$html .= '<select class="" id="' . esc_attr( $args['key'] ) . '" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . ']">' . "\n";
481
				foreach ( $args['data']['options'] as $k => $v ) {
482
					$html .= '<option value="' . esc_attr( $k ) . '"' . selected( esc_attr( $options[$args['key']] ), $k, false ) . '>' . $v . '</option>' . "\n";
483
				}
484
			$html .= '</select>' . "\n";
485
			echo $html;
486
487
			if ( isset( $args['data']['description'] ) ) {
488
				echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
489
			}
490
		}
491
	} // End form_field_select()
492
493
	/**
494
	 * Generate radio button field.
495
	 * @access public
496
	 * @since  1.0.0
497
	 * @param  array $args
498
	 * @return void
499
	 */
500 View Code Duplication
	public function form_field_radio ( $args ) {
501
		$options = $this->get_settings();
502
503
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
504
			$html = '';
505
			foreach ( $args['data']['options'] as $k => $v ) {
506
				$html .= '<input type="radio" name="' . $this->token . '[' . esc_attr( $args['key'] ) . ']" value="' . esc_attr( $k ) . '"' . checked( esc_attr( $options[$args['key']] ), $k, false ) . ' /> ' . $v . '<br />' . "\n";
507
			}
508
			echo $html;
509
510
			if ( isset( $args['data']['description'] ) ) {
511
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
512
			}
513
		}
514
	} // End form_field_radio()
515
516
	/**
517
	 * Generate multicheck field.
518
	 * @access public
519
	 * @since  1.0.0
520
	 * @param  array $args
521
	 * @return void
522
	 */
523
	public function form_field_multicheck ( $args ) {
524
		$options = $this->get_settings();
525
526
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
527
			$html = '<div class="multicheck-container" style="margin-bottom:10px;">' . "\n";
528
			foreach ( $args['data']['options'] as $k => $v ) {
529
				$checked = '';
530
531
				if( isset( $options[ $args['key'] ] ) ) {
532
					if ( in_array( $k, (array)$options[ $args['key'] ] ) ) { $checked = ' checked="checked"'; }
533
				} else {
534
					if ( in_array( $k, $args['data']['defaults'] ) ) { $checked = ' checked="checked"'; }
535
				}
536
				$html .= '<label for="checkbox-' . esc_attr( $k ) . '">' . "\n";
537
				$html .= '<input type="checkbox" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . '][]" class="multicheck multicheck-' . esc_attr( $args['key'] ) . '" value="' . esc_attr( $k ) . '" id="checkbox-' . esc_attr( $k ) . '" ' . $checked . ' /> ' . $v . "\n";
538
				$html .= '</label><br />' . "\n";
539
			}
540
			$html .= '</div>' . "\n";
541
			echo $html;
542
543
			if ( isset( $args['data']['description'] ) ) {
544
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
545
			}
546
		}
547
	} // End form_field_multicheck()
548
549
	/**
550
	 * Generate range field.
551
	 * @access public
552
	 * @since  1.0.0
553
	 * @param  array $args
554
	 * @return void
555
	 */
556 View Code Duplication
	public function form_field_range ( $args ) {
557
		$options = $this->get_settings();
558
559
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
560
			$html = '';
561
			$html .= '<select id="' . esc_attr( $args['key'] ) . '" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . ']" class="range-input">' . "\n";
562
				foreach ( $args['data']['options'] as $k => $v ) {
563
					$html .= '<option value="' . esc_attr( $k ) . '"' . selected( esc_attr( $options[$args['key']] ), $k, false ) . '>' . $v . '</option>' . "\n";
564
				}
565
			$html .= '</select>' . "\n";
566
			echo $html;
567
568
			if ( isset( $args['data']['description'] ) ) {
569
				echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
570
			}
571
		}
572
	} // End form_field_range()
573
574
	/**
575
	 * Generate image-based selector form field.
576
	 * @access public
577
	 * @since  1.0.0
578
	 * @param  array $args
579
	 * @return void
580
	 */
581 View Code Duplication
	public function form_field_images ( $args ) {
582
		$options = $this->get_settings();
583
584
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
585
			$html = '';
586
			foreach ( $args['data']['options'] as $k => $v ) {
587
				$html .= '<input type="radio" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . ']" value="' . esc_attr( $k ) . '"' . checked( esc_attr( $options[$args['key']] ), $k, false ) . ' /> ' . $v . '<br />' . "\n";
588
			}
589
			echo $html;
590
591
			if ( isset( $args['data']['description'] ) ) {
592
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
593
			}
594
		}
595
	} // End form_field_images()
596
597
	/**
598
	 * Generate information box field.
599
	 * @access public
600
	 * @since  1.0.0
601
	 * @param  array $args
602
	 * @return void
603
	 */
604
	public function form_field_info ( $args ) {
605
		$class = '';
606 View Code Duplication
		if ( isset( $args['data']['class'] ) ) {
607
			$class = ' ' . esc_attr( $args['data']['class'] );
608
		}
609
		$html = '<div id="' . $args['key'] . '" class="info-box' . $class . '">' . "\n";
610 View Code Duplication
		if ( isset( $args['data']['name'] ) && ( $args['data']['name'] != '' ) ) {
611
			$html .= '<h3 class="title">' . esc_html( $args['data']['name'] ) . '</h3>' . "\n";
612
		}
613 View Code Duplication
		if ( isset( $args['data']['description'] ) && ( $args['data']['description'] != '' ) ) {
614
			$html .= '<p>' . esc_html( $args['data']['description'] ) . '</p>' . "\n";
615
		}
616
		$html .= '</div>' . "\n";
617
618
		echo $html;
619
	} // End form_field_info()
620
621
622
	/**
623
	 * Generate button field.
624
	 * @access public
625
	 * @since  1.9.0
626
	 * @param  array $args
627
	 */
628
	public function form_field_button( $args ) {
629
		$options = $this->get_settings();
630
631
		if ( isset( $args['data']['target'] ) && isset( $args['data']['label'] ) ) {
632
			printf( '<a href="%s" class="button button-secondary">%s</a> ', esc_url( $args['data']['target'] ), esc_html( $args['data']['label'] ) );
633
634
			if ( isset( $args['data']['description'] ) ) {
635
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
636
			}
637
		}
638
	} // End form_field_button()
639
640
641
	/**
642
	 * Validate registered settings fields.
643
	 * @access public
644
	 * @since  1.0.0
645
	 * @param  array $input
646
	 * @uses   $this->parse_errors()
647
	 * @return array $options
648
	 */
649
	public function validate_fields ( $input ) {
650
		$options = $this->get_settings();
651
652
		foreach ( $this->fields as $k => $v ) {
653
			// Make sure checkboxes are present even when false.
654 View Code Duplication
			if ( $v['type'] == 'checkbox' && ! isset( $input[$k] ) ) { $input[$k] = false; }
655 View Code Duplication
			if ( $v['type'] == 'multicheck' && ! isset( $input[$k] ) ) { $input[$k] = false; }
656
657
			if ( isset( $input[$k] ) ) {
658
				// Perform checks on required fields.
659
				if ( isset( $v['required'] ) && ( $v['required'] == true ) ) {
660
					if ( in_array( $v['type'], $this->get_array_field_types() ) && ( count( (array) $input[$k] ) <= 0 ) ) {
661
						$this->add_error( $k, $v );
662
						continue;
663
					} else {
664
						if ( $input[$k] == '' ) {
665
							$this->add_error( $k, $v );
666
							continue;
667
						}
668
					}
669
				}
670
671
				$value = $input[$k];
672
673
				// Check if the field is valid.
674
				$method = $this->determine_method( $v, 'check' );
675
676 View Code Duplication
				if ( function_exists ( $method ) ) {
677
					$is_valid = $method( $value );
678
				} else {
679
					if ( method_exists( $this, $method ) ) {
680
						$is_valid = $this->$method( $value );
681
					}
682
				}
683
684
				if ( ! $is_valid ) {
685
					$this->add_error( $k, $v );
686
					continue;
687
				}
688
689
				$method = $this->determine_method( $v, 'validate' );
690
691 View Code Duplication
				if ( function_exists ( $method ) ) {
692
					$options[$k] = $method( $value );
693
				} else {
694
					if ( method_exists( $this, $method ) ) {
695
						$options[$k] = $this->$method( $value );
696
					}
697
				}
698
			}
699
		}
700
701
		// Parse error messages into the Settings API.
702
		$this->parse_errors();
703
		return $options;
704
	} // End validate_fields()
705
706
	/**
707
	 * Validate text fields.
708
	 * @access public
709
	 * @since  1.0.0
710
	 * @param  string $input
711
	 * @return string
712
	 */
713
	public function validate_field_text ( $input ) {
714
		return trim( esc_attr( $input ) );
715
	} // End validate_field_text()
716
717
	/**
718
	 * Validate checkbox fields.
719
	 * @access public
720
	 * @since  1.0.0
721
	 * @param  string $input
722
	 * @return string
723
	 */
724
	public function validate_field_checkbox ( $input ) {
725
		if ( ! isset( $input ) ) {
726
			return 0;
727
		} else {
728
			return (bool)$input;
729
		}
730
	} // End validate_field_checkbox()
731
732
	/**
733
	 * Validate multicheck fields.
734
	 * @access public
735
	 * @since  1.0.0
736
	 * @param  string $input
737
	 * @return string
738
	 */
739
	public function validate_field_multicheck ( $input ) {
740
		$input = (array) $input;
741
742
		$input = array_map( 'esc_attr', $input );
743
744
		return $input;
745
	} // End validate_field_multicheck()
746
747
	/**
748
	 * Validate range fields.
749
	 * @access public
750
	 * @since  1.0.0
751
	 * @param  string $input
752
	 * @return string
753
	 */
754
	public function validate_field_range ( $input ) {
755
		$input = number_format( floatval( $input ), 0 );
756
757
		return $input;
758
	} // End validate_field_range()
759
760
	/**
761
	 * Validate URL fields.
762
	 * @access public
763
	 * @since  1.0.0
764
	 * @param  string $input
765
	 * @return string
766
	 */
767
	public function validate_field_url ( $input ) {
768
		return trim( esc_url( $input ) );
769
	} // End validate_field_url()
770
771
	/**
772
	 * Check and validate the input from text fields.
773
	 * @param  string $input String of the value to be validated.
774
	 * @since  1.1.0
775
	 * @return boolean Is the value valid?
776
	 */
777
	public function check_field_text ( $input ) {
778
		$is_valid = true;
779
780
		return $is_valid;
781
	} // End check_field_text()
782
783
	/**
784
	 * Log an error internally, for processing later using $this->parse_errors().
785
	 * @access protected
786
	 * @since  1.0.0
787
	 * @param  string $key
788
	 * @param  array $data
789
	 * @return void
790
	 */
791
	protected function add_error ( $key, $data ) {
792
		if ( isset( $data['error_message'] ) ) {
793
			$message = $data['error_message'];
794
		} else {
795
			$message = sprintf( __( '%s is a required field', 'woothemes-sensei' ), $data['name'] );
796
		}
797
		$this->errors[$key] = $message;
798
	} // End add_error()
799
800
	/**
801
	 * Parse logged errors.
802
	 * @access  protected
803
	 * @since   1.0.0
804
	 * @return  void
805
	 */
806
	protected function parse_errors () {
807
		if ( count ( $this->errors ) > 0 ) {
808
			foreach ( $this->errors as $k => $v ) {
809
				add_settings_error( $this->token . '-errors', $k, $v, 'error' );
810
			}
811
		} else {
812
			$message = sprintf( __( '%s updated', 'woothemes-sensei' ), $this->name );
813
			add_settings_error( $this->token . '-errors', $this->token, $message, 'updated' );
814
		}
815
	} // End parse_errors()
816
817
	/**
818
	 * Return an array of field types expecting an array value returned.
819
	 * @access protected
820
	 * @since  1.0.0
821
	 * @return array
822
	 */
823
	protected function get_array_field_types () {
824
		return array( 'multicheck' );
825
	} // End get_array_field_types()
826
827
	/**
828
	 * Load in JavaScripts where necessary.
829
	 * @access public
830
	 * @since  1.0.0
831
	 * @return void
832
	 */
833
	public function enqueue_scripts () {
834
835
        $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
836
837
		wp_enqueue_script( 'farbtastic' );
838
		wp_enqueue_script( 'woothemes-sensei-settings', esc_url( Sensei()->plugin_url . 'assets/js/settings' . $suffix . '.js' ), array( 'jquery', 'farbtastic' ), Sensei()->version );
839
840 View Code Duplication
		if ( $this->has_range ) {
841
			wp_enqueue_script( 'woothemes-sensei-settings-ranges', esc_url( Sensei()->plugin_url . 'assets/js/ranges' . $suffix . '.js' ), array( 'jquery-ui-slider' ), Sensei()->version );
842
		}
843
844
		wp_register_script( 'woothemes-sensei-settings-imageselectors', esc_url( Sensei()->plugin_url . 'assets/js/image-selectors' . $suffix . '.js' ), array( 'jquery' ), Sensei()->version );
845
846
		if ( $this->has_imageselector ) {
847
			wp_enqueue_script( 'woothemes-sensei-settings-imageselectors' );
848
		}
849
850
	} // End enqueue_scripts()
851
852
	/**
853
	 * Load in CSS styles where necessary.
854
	 * @access public
855
	 * @since  1.0.0
856
	 * @return void
857
	 */
858
	public function enqueue_styles () {
859
860
		wp_enqueue_style( $this->token . '-admin' );
861
862
		wp_enqueue_style( 'farbtastic' );
863
		wp_enqueue_style( 'woothemes-sensei-settings-api', esc_url( Sensei()->plugin_url . 'assets/css/settings.css' ), array( 'farbtastic' ), Sensei()->version );
864
865
		$this->enqueue_field_styles();
866
	} // End enqueue_styles()
867
868
	/**
869
	 * Load in CSS styles for field types where necessary.
870
	 * @access public
871
	 * @since  1.0.0
872
	 * @return void
873
	 */
874
	public function enqueue_field_styles () {
875
876 View Code Duplication
		if ( $this->has_range ) {
877
			wp_enqueue_style( 'woothemes-sensei-settings-ranges', esc_url( Sensei()->plugin_url . 'assets/css/ranges.css' ), '', Sensei()->version );
878
		}
879
880
		wp_register_style( 'woothemes-sensei-settings-imageselectors', esc_url( Sensei()->plugin_url . 'assets/css/image-selectors.css' ), '', Sensei()->version );
881
882
		if ( $this->has_imageselector ) {
883
			wp_enqueue_style( 'woothemes-sensei-settings-imageselectors' );
884
		}
885
	} // End enqueue_field_styles()
886
} // End Class
887
888
/**
889
 * Class WooThemes_Sensei_Settings_API
890
 * @ignore only for backward compatibility
891
 * @since 1.9.0
892
 */
893
class WooThemes_Sensei_Settings_API extends Sensei_Settings_API{}
894