Completed
Push — master ( 4fba21...48ea7a )
by Dwain
07:35
created

Sensei_Settings_API::settings_screen()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 41
Code Lines 29

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 41
rs 8.5806
cc 4
eloc 29
nc 6
nop 0
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();
0 ignored issues
show
Bug introduced by
The property remaining_fields does not seem to exist. Did you mean fields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
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' ) );
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 ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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'] ) . '"'; }
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 );
0 ignored issues
show
Unused Code Comprehensibility introduced by
59% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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; }
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
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
Documentation introduced by
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'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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;
0 ignored issues
show
Bug introduced by
The property remaining_fields does not seem to exist. Did you mean fields?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
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' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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;
0 ignored issues
show
Bug introduced by
The property hook does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
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
		if ( ! is_array( $this->settings ) ) {
345
			$this->settings = get_option( $this->token, array() );
346
		}
347
348
		foreach ( $this->fields as $k => $v ) {
349
			if ( ! isset( $this->settings[$k] ) && isset( $v['default'] ) ) {
350
				$this->settings[$k] = $v['default'];
351
			}
352
			if ( $v['type'] == 'checkbox' && $this->settings[$k] != true ) {
353
				$this->settings[$k] = 0;
354
			}
355
		}
356
357
		return $this->settings;
358
	} // End get_settings()
359
360
	/**
361
	 * Register the settings fields.
362
	 * @access public
363
	 * @since  1.0.0
364
	 * @return void
365
	 */
366
	public function settings_fields () {
367
		register_setting( $this->token, $this->token, array( $this, 'validate_fields' ) );
368
		$this->create_sections();
369
		$this->create_fields();
370
	} // End settings_fields()
371
372
	/**
373
	 * Display settings errors.
374
	 * @access public
375
	 * @since  1.0.0
376
	 * @return void
377
	 */
378
	public function settings_errors () {
379
        settings_errors( $this->token . '-errors' );
380
	} // End settings_errors()
381
382
	/**
383
	 * Display the description for a settings section.
384
	 * @access public
385
	 * @since  1.0.0
386
	 * @return void
387
	 */
388
	public function section_description ( $section ) {
389 View Code Duplication
		if ( isset( $this->sections[$section['id']]['description'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
390
			echo wpautop( $this->sections[$section['id']]['description'] );
391
		}
392
	} // End section_description_main()
393
394
	/**
395
	 * Generate text input field.
396
	 * @access public
397
	 * @since  1.0.0
398
	 * @param  array $args
399
	 * @return void
400
	 */
401 View Code Duplication
	public function form_field_text ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
402
		$options = $this->get_settings();
403
404
		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";
405
		if ( isset( $args['data']['description'] ) ) {
406
			echo '<span class="description">' . $args['data']['description'] . '</span>' . "\n";
407
		}
408
	} // End form_field_text()
409
410
	/**
411
	 * Generate color picker field.
412
	 * @access public
413
	 * @since  1.6.0
414
	 * @param  array $args
415
	 * @return void
416
	 */
417 View Code Duplication
	public function form_field_color ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
418
		$options = $this->get_settings();
419
420
		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";
421
		echo '<div style="position:absolute;background:#FFF;z-index:99;border-radius:100%;" class="colorpicker"></div>';
422
		if ( isset( $args['data']['description'] ) ) {
423
			echo '<span class="description">' . $args['data']['description'] . '</span>' . "\n";
424
		}
425
	} // End form_field_text()
426
427
	/**
428
	 * Generate checkbox field.
429
	 * @access public
430
	 * @since  1.0.0
431
	 * @param  array $args
432
	 * @return void
433
	 */
434
	public function form_field_checkbox ( $args ) {
435
		$options = $this->get_settings();
436
437
		$has_description = false;
438
		if ( isset( $args['data']['description'] ) ) {
439
			$has_description = true;
440
			echo '<label for="' . esc_attr( $args['key'] ) . '">' . "\n";
441
		}
442
		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";
443
		if ( $has_description ) {
444
			echo wp_kses( $args['data']['description'], array( 'a' => array(
445
																	        'href' => array(),
446
																	        'title' => array()
447
																	    )
448
															)
449
						) . '</label>' . "\n";
450
		}
451
	} // End form_field_checkbox()
452
453
	/**
454
	 * Generate textarea field.
455
	 * @access public
456
	 * @since  1.0.0
457
	 * @param  array $args
458
	 * @return void
459
	 */
460 View Code Duplication
	public function form_field_textarea ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
461
		$options = $this->get_settings();
462
463
		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";
464
		if ( isset( $args['data']['description'] ) ) {
465
			echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
466
		}
467
	} // End form_field_textarea()
468
469
	/**
470
	 * Generate select box field.
471
	 * @access public
472
	 * @since  1.0.0
473
	 * @param  array $args
474
	 * @return void
475
	 */
476 View Code Duplication
	public function form_field_select ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
477
		$options = $this->get_settings();
478
479
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
480
			$html = '';
481
			$html .= '<select class="" id="' . esc_attr( $args['key'] ) . '" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . ']">' . "\n";
482
				foreach ( $args['data']['options'] as $k => $v ) {
483
					$html .= '<option value="' . esc_attr( $k ) . '"' . selected( esc_attr( $options[$args['key']] ), $k, false ) . '>' . $v . '</option>' . "\n";
484
				}
485
			$html .= '</select>' . "\n";
486
			echo $html;
487
488
			if ( isset( $args['data']['description'] ) ) {
489
				echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
490
			}
491
		}
492
	} // End form_field_select()
493
494
	/**
495
	 * Generate radio button field.
496
	 * @access public
497
	 * @since  1.0.0
498
	 * @param  array $args
499
	 * @return void
500
	 */
501 View Code Duplication
	public function form_field_radio ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
502
		$options = $this->get_settings();
503
504
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
505
			$html = '';
506
			foreach ( $args['data']['options'] as $k => $v ) {
507
				$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";
508
			}
509
			echo $html;
510
511
			if ( isset( $args['data']['description'] ) ) {
512
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
513
			}
514
		}
515
	} // End form_field_radio()
516
517
	/**
518
	 * Generate multicheck field.
519
	 * @access public
520
	 * @since  1.0.0
521
	 * @param  array $args
522
	 * @return void
523
	 */
524
	public function form_field_multicheck ( $args ) {
525
		$options = $this->get_settings();
526
527
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
528
			$html = '<div class="multicheck-container" style="margin-bottom:10px;">' . "\n";
529
			foreach ( $args['data']['options'] as $k => $v ) {
530
				$checked = '';
531
532
				if( isset( $options[ $args['key'] ] ) ) {
533
					if ( in_array( $k, (array)$options[ $args['key'] ] ) ) { $checked = ' checked="checked"'; }
534
				} else {
535
					if ( in_array( $k, $args['data']['defaults'] ) ) { $checked = ' checked="checked"'; }
536
				}
537
				$html .= '<label for="checkbox-' . esc_attr( $k ) . '">' . "\n";
538
				$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";
539
				$html .= '</label><br />' . "\n";
540
			}
541
			$html .= '</div>' . "\n";
542
			echo $html;
543
544
			if ( isset( $args['data']['description'] ) ) {
545
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
546
			}
547
		}
548
	} // End form_field_multicheck()
549
550
	/**
551
	 * Generate range field.
552
	 * @access public
553
	 * @since  1.0.0
554
	 * @param  array $args
555
	 * @return void
556
	 */
557 View Code Duplication
	public function form_field_range ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
558
		$options = $this->get_settings();
559
560
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
561
			$html = '';
562
			$html .= '<select id="' . esc_attr( $args['key'] ) . '" name="' . esc_attr( $this->token ) . '[' . esc_attr( $args['key'] ) . ']" class="range-input">' . "\n";
563
				foreach ( $args['data']['options'] as $k => $v ) {
564
					$html .= '<option value="' . esc_attr( $k ) . '"' . selected( esc_attr( $options[$args['key']] ), $k, false ) . '>' . $v . '</option>' . "\n";
565
				}
566
			$html .= '</select>' . "\n";
567
			echo $html;
568
569
			if ( isset( $args['data']['description'] ) ) {
570
				echo '<p><span class="description">' . esc_html( $args['data']['description'] ) . '</span></p>' . "\n";
571
			}
572
		}
573
	} // End form_field_range()
574
575
	/**
576
	 * Generate image-based selector form field.
577
	 * @access public
578
	 * @since  1.0.0
579
	 * @param  array $args
580
	 * @return void
581
	 */
582 View Code Duplication
	public function form_field_images ( $args ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
583
		$options = $this->get_settings();
584
585
		if ( isset( $args['data']['options'] ) && ( count( (array)$args['data']['options'] ) > 0 ) ) {
586
			$html = '';
587
			foreach ( $args['data']['options'] as $k => $v ) {
588
				$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";
589
			}
590
			echo $html;
591
592
			if ( isset( $args['data']['description'] ) ) {
593
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
594
			}
595
		}
596
	} // End form_field_images()
597
598
	/**
599
	 * Generate information box field.
600
	 * @access public
601
	 * @since  1.0.0
602
	 * @param  array $args
603
	 * @return void
604
	 */
605
	public function form_field_info ( $args ) {
606
		$class = '';
607 View Code Duplication
		if ( isset( $args['data']['class'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
608
			$class = ' ' . esc_attr( $args['data']['class'] );
609
		}
610
		$html = '<div id="' . $args['key'] . '" class="info-box' . $class . '">' . "\n";
611 View Code Duplication
		if ( isset( $args['data']['name'] ) && ( $args['data']['name'] != '' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
612
			$html .= '<h3 class="title">' . esc_html( $args['data']['name'] ) . '</h3>' . "\n";
613
		}
614 View Code Duplication
		if ( isset( $args['data']['description'] ) && ( $args['data']['description'] != '' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
615
			$html .= '<p>' . esc_html( $args['data']['description'] ) . '</p>' . "\n";
616
		}
617
		$html .= '</div>' . "\n";
618
619
		echo $html;
620
	} // End form_field_info()
621
622
623
	/**
624
	 * Generate button field.
625
	 * @access public
626
	 * @since  1.9.0
627
	 * @param  array $args
628
	 */
629
	public function form_field_button( $args ) {
630
		$options = $this->get_settings();
0 ignored issues
show
Unused Code introduced by
$options is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
631
632
		if ( isset( $args['data']['target'] ) && isset( $args['data']['label'] ) ) {
633
			printf( '<a href="%s" class="button button-secondary">%s</a> ', esc_url( $args['data']['target'] ), esc_html( $args['data']['label'] ) );
634
635
			if ( isset( $args['data']['description'] ) ) {
636
				echo '<span class="description">' . esc_html( $args['data']['description'] ) . '</span>' . "\n";
637
			}
638
		}
639
	} // End form_field_button()
640
641
642
	/**
643
	 * Validate registered settings fields.
644
	 * @access public
645
	 * @since  1.0.0
646
	 * @param  array $input
647
	 * @uses   $this->parse_errors()
648
	 * @return array $options
649
	 */
650
	public function validate_fields ( $input ) {
651
		$options = $this->get_settings();
652
653
		foreach ( $this->fields as $k => $v ) {
654
			// Make sure checkboxes are present even when false.
655 View Code Duplication
			if ( $v['type'] == 'checkbox' && ! isset( $input[$k] ) ) { $input[$k] = false; }
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
656 View Code Duplication
			if ( $v['type'] == 'multicheck' && ! isset( $input[$k] ) ) { $input[$k] = false; }
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
657
658
			if ( isset( $input[$k] ) ) {
659
				// Perform checks on required fields.
660
				if ( isset( $v['required'] ) && ( $v['required'] == true ) ) {
661
					if ( in_array( $v['type'], $this->get_array_field_types() ) && ( count( (array) $input[$k] ) <= 0 ) ) {
662
						$this->add_error( $k, $v );
663
						continue;
664
					} else {
665
						if ( $input[$k] == '' ) {
666
							$this->add_error( $k, $v );
667
							continue;
668
						}
669
					}
670
				}
671
672
				$value = $input[$k];
673
674
				// Check if the field is valid.
675
				$method = $this->determine_method( $v, 'check' );
676
677 View Code Duplication
				if ( function_exists ( $method ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
678
					$is_valid = $method( $value );
679
				} else {
680
					if ( method_exists( $this, $method ) ) {
681
						$is_valid = $this->$method( $value );
682
					}
683
				}
684
685
				if ( ! $is_valid ) {
0 ignored issues
show
Bug introduced by
The variable $is_valid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
686
					$this->add_error( $k, $v );
687
					continue;
688
				}
689
690
				$method = $this->determine_method( $v, 'validate' );
691
692 View Code Duplication
				if ( function_exists ( $method ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
693
					$options[$k] = $method( $value );
694
				} else {
695
					if ( method_exists( $this, $method ) ) {
696
						$options[$k] = $this->$method( $value );
697
					}
698
				}
699
			}
700
		}
701
702
		// Parse error messages into the Settings API.
703
		$this->parse_errors();
704
		return $options;
705
	} // End validate_fields()
706
707
	/**
708
	 * Validate text fields.
709
	 * @access public
710
	 * @since  1.0.0
711
	 * @param  string $input
712
	 * @return string
713
	 */
714
	public function validate_field_text ( $input ) {
715
		return trim( esc_attr( $input ) );
716
	} // End validate_field_text()
717
718
	/**
719
	 * Validate checkbox fields.
720
	 * @access public
721
	 * @since  1.0.0
722
	 * @param  string $input
723
	 * @return string
724
	 */
725
	public function validate_field_checkbox ( $input ) {
726
		if ( ! isset( $input ) ) {
727
			return 0;
728
		} else {
729
			return (bool)$input;
730
		}
731
	} // End validate_field_checkbox()
732
733
	/**
734
	 * Validate multicheck fields.
735
	 * @access public
736
	 * @since  1.0.0
737
	 * @param  string $input
738
	 * @return string
739
	 */
740
	public function validate_field_multicheck ( $input ) {
741
		$input = (array) $input;
742
743
		$input = array_map( 'esc_attr', $input );
744
745
		return $input;
746
	} // End validate_field_multicheck()
747
748
	/**
749
	 * Validate range fields.
750
	 * @access public
751
	 * @since  1.0.0
752
	 * @param  string $input
753
	 * @return string
754
	 */
755
	public function validate_field_range ( $input ) {
756
		$input = number_format( floatval( $input ), 0 );
757
758
		return $input;
759
	} // End validate_field_range()
760
761
	/**
762
	 * Validate URL fields.
763
	 * @access public
764
	 * @since  1.0.0
765
	 * @param  string $input
766
	 * @return string
767
	 */
768
	public function validate_field_url ( $input ) {
769
		return trim( esc_url( $input ) );
770
	} // End validate_field_url()
771
772
	/**
773
	 * Check and validate the input from text fields.
774
	 * @param  string $input String of the value to be validated.
775
	 * @since  1.1.0
776
	 * @return boolean Is the value valid?
777
	 */
778
	public function check_field_text ( $input ) {
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
779
		$is_valid = true;
780
781
		return $is_valid;
782
	} // End check_field_text()
783
784
	/**
785
	 * Log an error internally, for processing later using $this->parse_errors().
786
	 * @access protected
787
	 * @since  1.0.0
788
	 * @param  string $key
789
	 * @param  array $data
790
	 * @return void
791
	 */
792
	protected function add_error ( $key, $data ) {
793
		if ( isset( $data['error_message'] ) ) {
794
			$message = $data['error_message'];
795
		} else {
796
			$message = sprintf( __( '%s is a required field', 'woothemes-sensei' ), $data['name'] );
797
		}
798
		$this->errors[$key] = $message;
799
	} // End add_error()
800
801
	/**
802
	 * Parse logged errors.
803
	 * @access  protected
804
	 * @since   1.0.0
805
	 * @return  void
806
	 */
807
	protected function parse_errors () {
808
		if ( count ( $this->errors ) > 0 ) {
809
			foreach ( $this->errors as $k => $v ) {
810
				add_settings_error( $this->token . '-errors', $k, $v, 'error' );
811
			}
812
		} else {
813
			$message = sprintf( __( '%s updated', 'woothemes-sensei' ), $this->name );
814
			add_settings_error( $this->token . '-errors', $this->token, $message, 'updated' );
815
		}
816
	} // End parse_errors()
817
818
	/**
819
	 * Return an array of field types expecting an array value returned.
820
	 * @access protected
821
	 * @since  1.0.0
822
	 * @return array
823
	 */
824
	protected function get_array_field_types () {
825
		return array( 'multicheck' );
826
	} // End get_array_field_types()
827
828
	/**
829
	 * Load in JavaScripts where necessary.
830
	 * @access public
831
	 * @since  1.0.0
832
	 * @return void
833
	 */
834
	public function enqueue_scripts () {
835
836
        $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
837
838
		wp_enqueue_script( 'farbtastic' );
839
		wp_enqueue_script( 'woothemes-sensei-settings', esc_url( Sensei()->plugin_url . 'assets/js/settings' . $suffix . '.js' ), array( 'jquery', 'farbtastic' ), Sensei()->version );
840
841 View Code Duplication
		if ( $this->has_range ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
842
			wp_enqueue_script( 'woothemes-sensei-settings-ranges', esc_url( Sensei()->plugin_url . 'assets/js/ranges' . $suffix . '.js' ), array( 'jquery-ui-slider' ), Sensei()->version );
843
		}
844
845
		wp_register_script( 'woothemes-sensei-settings-imageselectors', esc_url( Sensei()->plugin_url . 'assets/js/image-selectors' . $suffix . '.js' ), array( 'jquery' ), Sensei()->version );
846
847
		if ( $this->has_imageselector ) {
848
			wp_enqueue_script( 'woothemes-sensei-settings-imageselectors' );
849
		}
850
851
	} // End enqueue_scripts()
852
853
	/**
854
	 * Load in CSS styles where necessary.
855
	 * @access public
856
	 * @since  1.0.0
857
	 * @return void
858
	 */
859
	public function enqueue_styles () {
860
861
		wp_enqueue_style( $this->token . '-admin' );
862
863
		wp_enqueue_style( 'farbtastic' );
864
		wp_enqueue_style( 'woothemes-sensei-settings-api', esc_url( Sensei()->plugin_url . 'assets/css/settings.css' ), array( 'farbtastic' ), Sensei()->version );
865
866
		$this->enqueue_field_styles();
867
	} // End enqueue_styles()
868
869
	/**
870
	 * Load in CSS styles for field types where necessary.
871
	 * @access public
872
	 * @since  1.0.0
873
	 * @return void
874
	 */
875
	public function enqueue_field_styles () {
876
877 View Code Duplication
		if ( $this->has_range ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
878
			wp_enqueue_style( 'woothemes-sensei-settings-ranges', esc_url( Sensei()->plugin_url . 'assets/css/ranges.css' ), '', Sensei()->version );
879
		}
880
881
		wp_register_style( 'woothemes-sensei-settings-imageselectors', esc_url( Sensei()->plugin_url . 'assets/css/image-selectors.css' ), '', Sensei()->version );
882
883
		if ( $this->has_imageselector ) {
884
			wp_enqueue_style( 'woothemes-sensei-settings-imageselectors' );
885
		}
886
	} // End enqueue_field_styles()
887
} // End Class
888
889
/**
890
 * Class WooThemes_Sensei_Settings_API
891
 * @ignore only for backward compatibility
892
 * @since 1.9.0
893
 */
894
class WooThemes_Sensei_Settings_API extends Sensei_Settings_API{}
895