PluginProbe
Orderable – Restaurant & Food Ordering System / 1.19.0
Orderable – Restaurant & Food Ordering System v1.19.0
0.1.4 0.1.5 0.2.0 1.0.0 1.1.0 1.1.1 1.10.0 1.10.1 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.14.0 1.15.0 1.16.0 1.17.0 1.17.1 1.18.0 1.19.0 1.19.1 1.19.2 1.2.0 1.20.0 1.20.1 All 44 releases
orderable / inc / vendor / wp-settings-framework / wp-settings-framework.php

wp-settings-framework.php in Orderable – Restaurant & Food Ordering System 1.19.0, at inc/vendor/wp-settings-framework/wp-settings-framework.php

1,691 lines 51.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WordPress Settings Framework
4 *
5 * @link https://github.com/gilbitron/WordPress-Settings-Framework
6 * @version 1.6.11
7 *
8 * @package wordpress-settings-framework
9 */
10
11 if ( ! class_exists( 'Orderable_Settings_Framework' ) ) {
12 /**
13 * Orderable_Settings_Framework class
14 */
15 class Orderable_Settings_Framework {
16 /**
17 * Settings wrapper.
18 *
19 * @var array
20 */
21 private $settings_wrapper;
22
23 /**
24 * Settings.
25 *
26 * @var array
27 */
28 private $settings;
29
30 /**
31 * Tabs.
32 *
33 * @var array
34 */
35 private $tabs;
36
37 /**
38 * Option group.
39 *
40 * @var string
41 */
42 private $option_group;
43
44 /**
45 * Settings page.
46 *
47 * @var array
48 */
49 public $settings_page = array();
50
51 /**
52 * Options path.
53 *
54 * @var string
55 */
56 private $options_path;
57
58 /**
59 * Options URL.
60 *
61 * @var string
62 */
63 private $options_url;
64
65 /**
66 * Setting defaults.
67 *
68 * @var array
69 */
70 protected $setting_defaults = array(
71 'id' => 'default_field',
72 'title' => 'Default Field',
73 'desc' => '',
74 'std' => '',
75 'type' => 'text',
76 'placeholder' => '',
77 'choices' => array(),
78 'class' => '',
79 'subfields' => array(),
80 'autocomplete' => '',
81 'attributes' => array(),
82 'custom_args' => array(),
83 );
84
85 /**
86 * Orderable_Settings_Framework constructor.
87 *
88 * @param null|string $settings_file Path to a settings file, or null if you pass the option_group manually and construct your settings with a filter.
89 * @param bool|string $option_group Option group name, usually a short slug.
90 */
91 public function __construct( $settings_file = null, $option_group = false ) {
92 $this->option_group = $option_group;
93
94 if ( $settings_file ) {
95 if ( ! is_file( $settings_file ) ) {
96 return;
97 }
98
99 require_once $settings_file;
100
101 if ( ! $this->option_group ) {
102 $this->option_group = preg_replace( '/[^a-z0-9]+/i', '', basename( $settings_file, '.php' ) );
103 }
104 }
105
106 if ( empty( $this->option_group ) ) {
107 return;
108 }
109
110 $this->options_path = plugin_dir_path( __FILE__ );
111 $this->options_url = plugin_dir_url( __FILE__ );
112
113 $this->construct_settings();
114
115 if ( is_admin() ) {
116 global $pagenow;
117
118 add_action( 'admin_init', array( $this, 'admin_init' ) );
119 add_action( 'wpsf_do_settings_sections_' . $this->option_group, array( $this, 'do_tabless_settings_sections' ), 10 );
120
121 if ( filter_input( INPUT_GET, 'page' ) && filter_input( INPUT_GET, 'page' ) === $this->settings_page['slug'] ) {
122 if ( 'options-general.php' !== $pagenow ) {
123 add_action( 'admin_notices', array( $this, 'admin_notices' ) );
124 }
125 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
126 }
127
128 if ( $this->has_tabs() ) {
129 add_action( 'wpsf_before_settings_' . $this->option_group, array( $this, 'tab_links' ) );
130
131 remove_action( 'wpsf_do_settings_sections_' . $this->option_group, array( $this, 'do_tabless_settings_sections' ), 10 );
132 add_action( 'wpsf_do_settings_sections_' . $this->option_group, array( $this, 'do_tabbed_settings_sections' ), 10 );
133 }
134
135 add_action( 'wp_ajax_wpsf_export_settings', array( $this, 'export_settings' ) );
136 add_action( 'wp_ajax_wpsf_import_settings', array( $this, 'import_settings' ) );
137 }
138 }
139
140 /**
141 * Construct Settings.
142 */
143 public function construct_settings() {
144 /**
145 * Filter: modify settings for a given option group.
146 *
147 * @filter wpsf_register_settings_<option_group>
148 * @since 1.6.9
149 * @param array
150 */
151 $this->settings_wrapper = apply_filters( 'wpsf_register_settings_' . $this->option_group, array() );
152
153 if ( ! is_array( $this->settings_wrapper ) ) {
154 return new WP_Error( 'broke', esc_html__( 'WPSF settings must be an array', 'wpsf' ) );
155 }
156
157 // If "sections" is set, this settings group probably has tabs.
158 if ( isset( $this->settings_wrapper['sections'] ) ) {
159 $this->tabs = ( isset( $this->settings_wrapper['tabs'] ) ) ? $this->settings_wrapper['tabs'] : array();
160 $this->settings = $this->settings_wrapper['sections'];
161 // If not, it's probably just an array of settings.
162 } else {
163 $this->settings = $this->settings_wrapper;
164 }
165
166 $this->settings_page['slug'] = sprintf( '%s-settings', str_replace( '_', '-', $this->option_group ) );
167 }
168
169 /**
170 * Get the option group for this instance
171 *
172 * @return string the "option_group"
173 */
174 public function get_option_group() {
175 return $this->option_group;
176 }
177
178 /**
179 * Registers the internal WordPress settings
180 */
181 public function admin_init() {
182 register_setting( $this->option_group, $this->option_group . '_settings', array( $this, 'settings_validate' ) );
183 $this->process_settings();
184 }
185
186 /**
187 * Add Settings Page
188 *
189 * @param array $args Settings page arguments.
190 */
191 public function add_settings_page( $args ) {
192 if ( ! $this->settings_page ) {
193 return;
194 }
195
196 $defaults = array(
197 'parent_slug' => false,
198 'page_slug' => '',
199 'page_title' => '',
200 'menu_title' => '',
201 'capability' => 'manage_options',
202 );
203
204 $args = wp_parse_args( $args, $defaults );
205
206 $this->settings_page['title'] = $args['page_title'];
207 $this->settings_page['capability'] = $args['capability'];
208
209 if ( $args['parent_slug'] ) {
210 add_submenu_page(
211 $args['parent_slug'],
212 $this->settings_page['title'],
213 $args['menu_title'],
214 $args['capability'],
215 $this->settings_page['slug'],
216 array( $this, 'settings_page_content' )
217 );
218 } else {
219 add_menu_page(
220 $this->settings_page['title'],
221 $args['menu_title'],
222 $args['capability'],
223 $this->settings_page['slug'],
224 array( $this, 'settings_page_content' ),
225 /**
226 * Filter: modify icon URL for a given option group.
227 *
228 * @filter wpsf_menu_icon_url_<option_group>
229 * @since 1.6.9
230 * @param string
231 */
232 apply_filters( 'wpsf_menu_icon_url_' . $this->option_group, '' ),
233 /**
234 * Filter: modify menu position for a given option group.
235 *
236 * @filter wpsf_menu_position_<option_group>
237 * @since 1.6.9
238 * @param int|null
239 */
240 apply_filters( 'wpsf_menu_position_' . $this->option_group, null )
241 );
242 }
243 }
244
245 /**
246 * Settings Page Content
247 */
248 public function settings_page_content() {
249 if ( ! current_user_can( $this->settings_page['capability'] ) ) {
250 wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wpsf' ) );
251 }
252 ?>
253 <div class="wpsf-settings wpsf-settings--<?php echo esc_attr( $this->option_group ); ?>">
254 <?php $this->settings_header(); ?>
255 <div class="wpsf-settings__content">
256 <?php $this->settings(); ?>
257 </div>
258 </div>
259 <?php
260 }
261
262 /**
263 * Settings Header.
264 */
265 public function settings_header() {
266 ?>
267 <div class="wpsf-settings__header">
268 <h2>
269 <?php
270 global $allowedposttags;
271 $protocols = wp_allowed_protocols();
272 $protocols[] = 'data';
273
274 echo wp_kses(
275 /**
276 * Filter: modify title for a given option group.
277 *
278 * @filter wpsf_title_<option_group>
279 * @since 1.6.9
280 * @param string $title Title for the group settings header.
281 */
282 apply_filters( 'wpsf_title_' . $this->option_group, $this->settings_page['title'] ),
283 $allowedposttags,
284 $protocols
285 );
286 ?>
287 </h2>
288 <?php
289 /**
290 * Hook: execute a callback after the option group title.
291 *
292 * @hook wpsf_after_title_<option_group>
293 * @since 1.6.9
294 */
295 do_action( 'wpsf_after_title_' . $this->option_group );
296 ?>
297 </div>
298 <?php
299 }
300
301 /**
302 * Displays any errors from the WordPress settings API
303 */
304 public function admin_notices() {
305 settings_errors();
306 }
307
308 /**
309 * Enqueue scripts and styles
310 */
311 public function admin_enqueue_scripts() {
312 // Scripts.
313 $jqtimepicker_js_path = 'assets/vendor/jquery-timepicker/jquery.ui.timepicker.js';
314 wp_register_script(
315 'jquery-ui-timepicker',
316 $this->options_url . $jqtimepicker_js_path,
317 array( 'jquery', 'jquery-ui-core' ),
318 filemtime( $this->options_path . $jqtimepicker_js_path ),
319 true
320 );
321
322 $wpsf_js_path = 'assets/js/main.js';
323 wp_register_script(
324 'wpsf',
325 $this->options_url . $wpsf_js_path,
326 array( 'jquery' ),
327 filemtime( $this->options_path . $wpsf_js_path ),
328 true
329 );
330
331 wp_enqueue_script( 'jquery' );
332 wp_enqueue_script( 'farbtastic' );
333 wp_enqueue_media();
334 wp_enqueue_script( 'media-upload' );
335 wp_enqueue_script( 'thickbox' );
336 wp_enqueue_script( 'jquery-ui-core' );
337 wp_enqueue_script( 'jquery-ui-datepicker' );
338 wp_enqueue_script( 'jquery-ui-timepicker' );
339 wp_enqueue_script( 'wpsf' );
340
341 $data = array(
342 'select_file' => esc_html__( 'Please select a file to import', 'wpsf' ),
343 'invalid_file' => esc_html__( 'Invalid file', 'wpsf' ),
344 'something_went_wrong' => esc_html__( 'Something went wrong', 'wpsf' ),
345 );
346 wp_localize_script( 'wpsf', 'wpsf_vars', $data );
347
348 // Styles.
349 $jqtimepicker_css_path = 'assets/vendor/jquery-timepicker/jquery.ui.timepicker.css';
350 wp_register_style(
351 'jquery-ui-timepicker',
352 $this->options_url . $jqtimepicker_css_path,
353 array(),
354 filemtime( $this->options_path . $jqtimepicker_css_path )
355 );
356
357 $wpsf_css_path = 'assets/css/main.css';
358 wp_register_style(
359 'wpsf',
360 $this->options_url . $wpsf_css_path,
361 array(),
362 filemtime( $this->options_path . $wpsf_css_path )
363 );
364
365 $jqui_css_path = 'assets/vendor/jquery-ui/jquery-ui.css';
366 wp_register_style(
367 'jquery-ui-css',
368 $this->options_url . $jqui_css_path,
369 array(),
370 filemtime( $this->options_path . $jqui_css_path )
371 );
372
373 wp_enqueue_style( 'farbtastic' );
374 wp_enqueue_style( 'thickbox' );
375 wp_enqueue_style( 'jquery-ui-timepicker' );
376 wp_enqueue_style( 'jquery-ui-css' );
377 wp_enqueue_style( 'wpsf' );
378
379 // Dequeue global style inlined by WordPress since WP 5.9.
380 wp_dequeue_style( 'global-styles' );
381 }
382
383 /**
384 * Adds a filter for settings validation.
385 *
386 * @param mixed $input Input data.
387 *
388 * @return array
389 */
390 public function settings_validate( $input ) {
391 /**
392 * Filter: validate field input for a given option group.
393 *
394 * @filter <option_group>_settings_validate
395 * @since 1.6.9
396 * @param mixed
397 */
398 return apply_filters( $this->option_group . '_settings_validate', $input );
399 }
400
401 /**
402 * Displays the "section_description" if specified in $this->settings
403 *
404 * @param array $args callback args from add_settings_section().
405 */
406 public function section_intro( $args ) {
407 if ( ! empty( $this->settings ) ) {
408 foreach ( $this->settings as $section ) {
409 if ( $section['section_id'] === $args['id'] ) {
410 $render_class = '';
411
412 $render_class .= self::add_show_hide_classes( $section );
413
414 if ( $render_class ) {
415 echo '<span class="' . esc_attr( $render_class ) . '"></span>';
416 }
417 if ( isset( $section['section_description'] ) && $section['section_description'] ) {
418 echo '<div class="wpsf-section-description wpsf-section-description--' . esc_attr( $section['section_id'] ) . '">' . wp_kses_post( $section['section_description'] ) . '</div>';
419 }
420 break;
421 }
422 }
423 }
424 }
425
426 /**
427 * Processes $this->settings and adds the sections and fields via the WordPress settings API
428 */
429 private function process_settings() {
430 if ( ! empty( $this->settings ) ) {
431 usort( $this->settings, array( $this, 'sort_array' ) );
432
433 foreach ( $this->settings as $section ) {
434 if ( isset( $section['section_id'] ) && $section['section_id'] && isset( $section['section_title'] ) ) {
435 $page_name = ( $this->has_tabs() ) ? sprintf( '%s_%s', $this->option_group, $section['tab_id'] ) : $this->option_group;
436
437 add_settings_section( $section['section_id'], $section['section_title'], array( $this, 'section_intro' ), $page_name );
438
439 if ( isset( $section['fields'] ) && is_array( $section['fields'] ) && ! empty( $section['fields'] ) ) {
440 foreach ( $section['fields'] as $field ) {
441 if ( isset( $field['id'] ) && $field['id'] && isset( $field['title'] ) ) {
442 $tooltip = '';
443
444 if ( isset( $field['link'] ) && is_array( $field['link'] ) ) {
445 $link_url = ( isset( $field['link']['url'] ) ) ? esc_html( $field['link']['url'] ) : '';
446 $link_text = ( isset( $field['link']['text'] ) ) ? esc_html( $field['link']['text'] ) : esc_html__( 'Learn More', 'wpsf' );
447 $link_external = ( isset( $field['link']['external'] ) ) ? (bool) $field['link']['external'] : true;
448 $link_type = ( isset( $field['link']['type'] ) ) ? esc_attr( $field['link']['type'] ) : 'tooltip';
449 $link_target = ( $link_external ) ? ' target="_blank"' : '';
450
451 if ( 'tooltip' === $link_type ) {
452 $link_text = sprintf( '<i class="dashicons dashicons-info wpsf-link-icon" title="%s"><span class="screen-reader-text">%s</span></i>', $link_text, $link_text );
453 }
454
455 $link = ( $link_url ) ? sprintf( '<a class="wpsf-label__link" href="%s"%s>%s</a>', $link_url, $link_target, $link_text ) : '';
456
457 if ( $link && 'tooltip' === $link_type ) {
458 $tooltip = $link;
459 } elseif ( $link ) {
460 $field['subtitle'] .= ( empty( $field['subtitle'] ) ) ? $link : sprintf( '<br/><br/>%s', $link );
461 }
462 }
463
464 $title = sprintf( '<span class="wpsf-label">%s %s</span>', $field['title'], $tooltip );
465
466 if ( ! empty( $field['subtitle'] ) ) {
467 $title .= sprintf( '<span class="wpsf-subtitle">%s</span>', $field['subtitle'] );
468 }
469
470 add_settings_field(
471 $field['id'],
472 $title,
473 array( $this, 'generate_setting' ),
474 $page_name,
475 $section['section_id'],
476 array(
477 'section' => $section,
478 'field' => $field,
479 )
480 );
481 }
482 }
483 }
484 }
485 }
486 }
487 }
488
489 /**
490 * Usort callback. Sorts $this->settings by "section_order"
491 *
492 * @param array $a Sortable Array.
493 * @param array $b Sortable Array.
494 *
495 * @return array
496 */
497 public function sort_array( $a, $b ) {
498 if ( ! isset( $a['section_order'] ) ) {
499 return 0;
500 }
501
502 return ( $a['section_order'] > $b['section_order'] ) ? 1 : 0;
503 }
504
505 /**
506 * Generates the HTML output of the settings fields
507 *
508 * @param array $args callback args from add_settings_field().
509 */
510 public function generate_setting( $args ) {
511 $section = $args['section'];
512 /**
513 * Filter: filter the default setting values for a given option group.
514 *
515 * @filter wpsf_defaults_<option_group>
516 * @since 1.6.9
517 * @param mixed $setting_defaults Default values for settings.
518 */
519 $this->setting_defaults = apply_filters( 'wpsf_defaults_' . $this->option_group, $this->setting_defaults );
520
521 $args = wp_parse_args( $args['field'], $this->setting_defaults );
522
523 $options = get_option( $this->option_group . '_settings' );
524
525 $args['id'] = ( $this->has_tabs() ) ? sprintf( '%s_%s_%s', $section['tab_id'], $section['section_id'], $args['id'] ) : sprintf( '%s_%s', $section['section_id'], $args['id'] );
526 $field_name = isset( $args['name'] ) ? $args['name'] : $args['id'];
527 $args['name'] = $this->generate_field_name( $field_name );
528 $args['value'] = ( isset( $options[ $field_name ] ) ) ? $options[ $field_name ] : ( isset( $args['default'] ) ? $args['default'] : '' );
529
530 $args['class'] .= self::add_show_hide_classes( $args );
531
532 /**
533 * Hook: execute callback before a given group.
534 *
535 * @hook wpsf_before_field_<option_group>
536 * @since 1.6.9
537 */
538 do_action( 'wpsf_before_field_' . $this->option_group );
539
540 /**
541 * Hook: execute callback before a specific field in a given group.
542 *
543 * @hook wpsf_before_field_<option_group>_<field_id>
544 * @since 1.6.9
545 */
546 do_action( 'wpsf_before_field_' . $this->option_group . '_' . $args['id'] );
547
548 $this->do_field_method( $args );
549
550 /**
551 * Hook: execute callback after a given group.
552 *
553 * @hook wpsf_after_field_<option_group>
554 * @since 1.6.9
555 */
556 do_action( 'wpsf_after_field_' . $this->option_group );
557
558 /**
559 * Hook: execute callback after a specific field in a given group.
560 *
561 * @hook wpsf_after_field_<option_group>_<field_id>
562 * @since 1.6.9
563 */
564 do_action( 'wpsf_after_field_' . $this->option_group . '_' . $args['id'] );
565 }
566
567 /**
568 * Do field method, if it exists
569 *
570 * @param array $args Field arguments.
571 */
572 public function do_field_method( $args ) {
573 $generate_field_method = sprintf( 'generate_%s_field', $args['type'] );
574
575 if ( method_exists( $this, $generate_field_method ) ) {
576 $this->$generate_field_method( $args );
577 }
578 }
579
580 /**
581 * Generate: Text field
582 *
583 * @param array $args Field arguments.
584 */
585 public function generate_text_field( $args ) {
586 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
587
588 echo '<input type="text" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" class="regular-text ' . esc_attr( $args['class'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
589
590 $this->generate_description( $args );
591 }
592
593 /**
594 * Generate: Hidden field.
595 *
596 * @param array $args Field arguments.
597 */
598 public function generate_hidden_field( $args ) {
599 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
600
601 echo '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" class="hidden-field ' . esc_attr( $args['class'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
602 }
603
604 /**
605 * Generate: Number field
606 *
607 * @param array $args Field arguments.
608 */
609 public function generate_number_field( $args ) {
610 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
611
612 echo '<input type="number" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" class="regular-text ' . esc_attr( $args['class'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
613
614 $this->generate_description( $args );
615 }
616
617 /**
618 * Generate: Time field
619 *
620 * @param array $args Field arguments.
621 */
622 public function generate_time_field( $args ) {
623 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
624
625 $timepicker = ( ! empty( $args['timepicker'] ) ) ? htmlentities( wp_json_encode( $args['timepicker'] ) ) : null;
626
627 echo '<input type="text" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" class="timepicker regular-text ' . esc_attr( $args['class'] ) . '" data-timepicker="' . esc_attr( $timepicker ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
628
629 $this->generate_description( $args );
630 }
631
632 /**
633 * Generate: Date field
634 *
635 * @param array $args Field arguments.
636 */
637 public function generate_date_field( $args ) {
638 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
639
640 $datepicker = ( ! empty( $args['datepicker'] ) ) ? htmlentities( wp_json_encode( $args['datepicker'] ) ) : null;
641
642 echo '<input type="text" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" class="datepicker regular-text ' . esc_attr( $args['class'] ) . '" data-datepicker="' . esc_attr( $datepicker ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
643
644 $this->generate_description( $args );
645 }
646
647 /**
648 * Generate Export Field.
649 *
650 * @param array $args Field arguments.
651 */
652 public function generate_export_field( $args ) {
653 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
654 $args['value'] = empty( $args['value'] ) ? esc_html__( 'Export Settings', 'wpsf' ) : $args['value'];
655 $option_group = $this->option_group;
656 $export_url = site_url() . '/wp-admin/admin-ajax.php?action=wpsf_export_settings&_wpnonce=' . wp_create_nonce( 'wpsf_export_settings' ) . '&option_group=' . $option_group;
657
658 echo '<a target=_blank href="' . esc_url( $export_url ) . '" class="button" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '">' . esc_html( $args['value'] ) . '</a>';
659
660 $options = get_option( $option_group . '_settings' );
661 $this->generate_description( $args );
662 }
663
664 /**
665 * Generate Import Field.
666 *
667 * @param array $args Field rguments.
668 */
669 public function generate_import_field( $args ) {
670 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
671 $args['value'] = empty( $args['value'] ) ? esc_html__( 'Import Settings', 'wpsf' ) : $args['value'];
672 $option_group = $this->option_group;
673
674 echo sprintf(
675 '
676 <div class="wpsf-import">
677 <div class="wpsf-import__false_btn">
678 <input type="file" name="wpsf-import-field" class="wpsf-import__file_field" id="%s" accept=".json"/>
679 <button type="button" name="wpsf_import_button" class="button wpsf-import__button" id="%s">%s</button>
680 <input type="hidden" class="wpsf_import_nonce" value="%s"></input>
681 <input type="hidden" class="wpsf_import_option_group" value="%s"></input>
682 </div>
683 <span class="spinner"></span>
684 </div>',
685 esc_attr( $args['id'] ),
686 esc_attr( $args['id'] ),
687 esc_attr( $args['value'] ),
688 esc_attr( wp_create_nonce( 'wpsf_import_settings' ) ),
689 esc_attr( $this->option_group )
690 );
691
692 $this->generate_description( $args );
693 }
694
695 /**
696 * Generate: Group field
697 *
698 * Generates a table of subfields, and a javascript template for create new repeatable rows
699 *
700 * @param array $args Field arguments.
701 */
702 public function generate_group_field( $args ) {
703 $value = (array) $args['value'];
704 $row_count = ( ! empty( $value ) ) ? count( $value ) : 1;
705
706 echo '<table id="group-' . esc_attr( str_replace( '_', '-', $args['id'] ) ) . '" class="' . esc_attr( $args['class'] ) . ' widefat wpsf-group" cellspacing="0">';
707
708 echo '<tbody>';
709
710 for ( $row = 0; $row < $row_count; $row ++ ) {
711 // @codingStandardsIgnoreStart
712 echo $this->generate_group_row_template( $args, false, $row );
713 // @codingStandardsIgnoreEnd
714 }
715
716 echo '</tbody>';
717
718 echo '</table>';
719
720 $this->generate_description( $args );
721
722 printf(
723 '<script type="text/html" id="%s_template">%s</script>',
724 esc_attr( $args['id'] ),
725 // @codingStandardsIgnoreStart
726 $this->generate_group_row_template( $args, true )
727 // @codingStandardsIgnoreEnd
728 );
729
730 $this->generate_description( $args );
731 }
732
733
734 /**
735 * Generate Image Checkboxes.
736 *
737 * @param array $args Field arguments.
738 *
739 * @return void
740 */
741 public function generate_image_checkboxes_field( $args ) {
742
743 echo '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="0" />';
744
745 echo '<ul class="wpsf-visual-field wpsf-visual-field--image-checkboxes wpsf-visual-field--grid wpsf-visual-field--cols">';
746
747 foreach ( $args['choices'] as $value => $choice ) {
748 $field_id = sprintf( '%s_%s', $args['id'], $value );
749 $is_checked = is_array( $args['value'] ) && in_array( $value, $args['value'], true );
750 $checked_class = $is_checked ? 'wpsf-visual-field__item--checked' : '';
751
752 echo sprintf(
753 '<li class="wpsf-visual-field__item %s">
754 <label>
755 <div class="wpsf-visual-field-image-radio__img_wrap">
756 <img src="%s">
757 </div>
758 <div class="wpsf-visual-field__item-footer">
759 <input type="checkbox" name="%s[]" id="%s" value="%s" class="%s" %s>
760 <span class="wpsf-visual-field__item-text">%s</span>
761 </div>
762 </label>
763 </li>',
764 esc_attr( $checked_class ),
765 esc_url( $choice['image'] ),
766 esc_attr( $args['name'] ),
767 esc_attr( $field_id ),
768 esc_attr( $value ),
769 esc_attr( $args['class'] ),
770 checked( true, $is_checked, false ),
771 esc_attr( $choice['text'] )
772 );
773 }
774
775 echo '</ul>';
776
777 $this->generate_description( $args );
778 }
779
780 /**
781 * Generate: Image Radio field
782 *
783 * @param array $args Field arguments.
784 */
785 public function generate_image_radio_field( $args ) {
786 $args['value'] = esc_html( esc_attr( $args['value'] ) );
787 $count = count( $args['choices'] );
788
789 echo sprintf( '<ul class="wpsf-visual-field wpsf-visual-field--image-radio wpsf-visual-field--grid wpsf-visual-field--cols wpsf-visual-field--col-%s ">', esc_attr( $count ) );
790
791 foreach ( $args['choices'] as $value => $choice ) {
792 $field_id = sprintf( '%s_%s', $args['id'], $value );
793 $checked = $value === $args['value'] ? 'checked="checked"' : '';
794
795 echo sprintf(
796 '<li class="wpsf-visual-field__item %s">
797 <label>
798 <div class="wpsf-visual-field-image-radio__img_wrap">
799 <img src="%s">
800 </div>
801 <div class="wpsf-visual-field__item-footer">
802 <input type="radio" name="%s" id="%s" value="%s" class="%s" %s>
803 <span class="wpsf-visual-field__item-text">%s</span>
804 </div>
805 </label>
806 </li>',
807 ( $checked ? 'wpsf-visual-field__item--checked' : '' ),
808 esc_attr( $choice['image'] ),
809 esc_attr( $args['name'] ),
810 esc_attr( $field_id ),
811 esc_attr( $value ),
812 esc_attr( $args['class'] ),
813 esc_html( $checked ),
814 esc_attr( $choice['text'] )
815 );
816 }
817 echo '</ul>';
818
819 $this->generate_description( $args );
820 }
821
822 /**
823 * Generate group row template
824 *
825 * @param array $args Field arguments.
826 * @param bool $blank Blank values.
827 * @param int $row Iterator.
828 *
829 * @return string|bool
830 */
831 public function generate_group_row_template( $args, $blank = false, $row = 0 ) {
832 $row_template = false;
833 $row_id = ( ! empty( $args['value'][ $row ]['row_id'] ) ) ? $args['value'][ $row ]['row_id'] : $row;
834 $row_id_value = ( $blank ) ? '' : $row_id;
835
836 if ( $args['subfields'] ) {
837 $row_class = ( 0 === $row % 2 ) ? 'alternate' : '';
838
839 $row_template .= sprintf( '<tr class="wpsf-group__row %s">', $row_class );
840
841 $row_template .= sprintf( '<td class="wpsf-group__row-index"><span>%d</span></td>', $row );
842
843 $row_template .= '<td class="wpsf-group__row-fields">';
844
845 $row_template .= '<input type="hidden" class="wpsf-group__row-id" name="' . sprintf( '%s[%d][row_id]', esc_attr( $args['name'] ), esc_attr( $row ) ) . '" value="' . esc_attr( $row_id_value ) . '" />';
846
847 foreach ( $args['subfields'] as $subfield ) {
848 $subfield = wp_parse_args( $subfield, $this->setting_defaults );
849
850 $subfield['value'] = ( $blank ) ? '' : ( isset( $args['value'][ $row ][ $subfield['id'] ] ) ? $args['value'][ $row ][ $subfield['id'] ] : '' );
851 $subfield['name'] = sprintf( '%s[%d][%s]', $args['name'], $row, $subfield['id'] );
852 $subfield['id'] = sprintf( '%s_%d_%s', $args['id'], $row, $subfield['id'] );
853
854 $class = sprintf( 'wpsf-group__field-wrapper--%s', $subfield['type'] );
855
856 $row_template .= sprintf( '<div class="wpsf-group__field-wrapper %s">', $class );
857 $row_template .= sprintf( '<label for="%s" class="wpsf-group__field-label">%s</label>', $subfield['id'], $subfield['title'] );
858
859 ob_start();
860 $this->do_field_method( $subfield );
861 $row_template .= ob_get_clean();
862
863 $row_template .= '</div>';
864 }
865
866 $row_template .= '</td>';
867
868 $row_template .= '<td class="wpsf-group__row-actions">';
869
870 $row_template .= sprintf( '<a href="javascript: void(0);" class="wpsf-group__row-add" data-template="%s_template"><span class="dashicons dashicons-plus-alt"></span></a>', $args['id'] );
871 $row_template .= '<a href="javascript: void(0);" class="wpsf-group__row-remove"><span class="dashicons dashicons-trash"></span></a>';
872
873 $row_template .= '</td>';
874
875 $row_template .= '</tr>';
876 }
877
878 return $row_template;
879 }
880
881 /**
882 * Generate: Select field
883 *
884 * @param array $args Field rguments.
885 */
886 public function generate_select_field( $args ) {
887 $is_multiple = isset( $args['multiple'] ) && filter_var( $args['multiple'], FILTER_VALIDATE_BOOLEAN );
888 $multiple = $is_multiple ? ' multiple="true" ' : ' ';
889
890 if ( $is_multiple ) {
891 $args['name'] .= '[]';
892 }
893
894 $values = (array) $args['value'];
895 $values = array_map( 'strval', $values );
896
897 echo '<select ' . esc_html( $multiple ) . ' name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" class="' . esc_attr( $args['class'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '>';
898
899 foreach ( $args['choices'] as $value => $text ) {
900 if ( is_array( $text ) ) {
901 echo sprintf( '<optgroup label="%s">', esc_html( $value ) );
902 foreach ( $text as $group_value => $group_text ) {
903 $selected = in_array( (string) $group_value, $values, true ) ? ' selected="selected" ' : '';
904 echo sprintf( '<option value="%s" %s>%s</option>', esc_attr( $group_value ), esc_html( $selected ), esc_html( $group_text ) );
905 }
906 echo '</optgroup>';
907 continue;
908 }
909
910 $selected = in_array( (string) $value, $values, true ) ? ' selected="selected" ' : '';
911 echo sprintf( '<option value="%s" %s>%s</option>', esc_attr( $value ), esc_html( $selected ), esc_html( $text ) );
912 }
913
914 echo '</select>';
915
916 $this->generate_description( $args );
917 }
918
919 /**
920 * Generate: Password field
921 *
922 * @param array $args Field arguments.
923 */
924 public function generate_password_field( $args ) {
925 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
926
927 echo '<input type="password" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="' . esc_attr( $args['value'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" class="regular-text ' . esc_attr( $args['class'] ) . '" autocomplete="' . esc_attr( $args['autocomplete'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '/>';
928
929 $this->generate_description( $args );
930 }
931
932 /**
933 * Generate: Textarea field
934 *
935 * @param array $args Field arguments.
936 */
937 public function generate_textarea_field( $args ) {
938 $args['value'] = esc_html( esc_attr( $args['value'] ) );
939 $rows = ( ! empty( $args['attributes']['rows'] ) ) ? absint( $args['attributes']['rows'] ) : 5;
940 $cols = ( ! empty( $args['attributes']['cols'] ) ) ? absint( $args['attributes']['cols'] ) : 60;
941
942 echo '<textarea name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" rows="' . esc_attr( $rows ) . '" cols="' . esc_attr( $cols ) . '" class="' . esc_attr( $args['class'] ) . '" ' . $this->array_to_html_atts( $args['attributes'] ) . '>' . esc_html( $args['value'] ) . '</textarea>';
943
944 $this->generate_description( $args );
945 }
946
947 /**
948 * Generate: Radio field
949 *
950 * @param array $args Field arguments.
951 */
952 public function generate_radio_field( $args ) {
953 $args['value'] = esc_html( esc_attr( $args['value'] ) );
954
955 foreach ( $args['choices'] as $value => $text ) {
956 $field_id = sprintf( '%s_%s', $args['id'], $value );
957 $checked = ( $value === $args['value'] ) ? 'checked="checked"' : '';
958
959 echo sprintf( '<label><input type="radio" name="%s" id="%s" value="%s" class="%s" %s> %s</label><br />', esc_attr( $args['name'] ), esc_attr( $field_id ), esc_html( $value ), esc_attr( $args['class'] ), esc_html( $checked ), esc_html( $text ) );
960 }
961
962 $this->generate_description( $args );
963 }
964
965 /**
966 * Generate: Checkbox field
967 *
968 * @param array $args Field arguments.
969 */
970 public function generate_checkbox_field( $args ) {
971 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
972 $checked = ( $args['value'] ) ? 'checked="checked"' : '';
973
974 echo '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="0" />';
975 echo '<label><input type="checkbox" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" class="' . esc_attr( $args['class'] ) . '" ' . esc_html( $checked ) . '> ' . esc_attr( $args['desc'] ) . '</label>';
976 }
977
978 /**
979 * Generate: Toggle field
980 *
981 * @param array $args Field arguments.
982 */
983 public function generate_toggle_field( $args ) {
984 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
985 $checked = ( $args['value'] ) ? 'checked="checked"' : '';
986
987 echo '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="0" />';
988 echo '<label class="switch"><input type="checkbox" name="' . esc_attr( $args['name'] ) . '" id="' . esc_attr( $args['id'] ) . '" value="1" class="' . esc_attr( $args['class'] ) . '" ' . esc_html( $checked ) . '> ' . esc_html( $args['desc'] ) . '<span class="slider"></span></label>';
989 }
990
991 /**
992 * Generate: Checkboxes field
993 *
994 * @param array $args Field arguments.
995 */
996 public function generate_checkboxes_field( $args ) {
997 echo '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="0" />';
998
999 echo '<ul class="wpsf-list wpsf-list--checkboxes">';
1000
1001 foreach ( $args['choices'] as $value => $text ) {
1002 $checked = ( is_array( $args['value'] ) && in_array( strval( $value ), array_map( 'strval', $args['value'] ), true ) ) ? 'checked="checked"' : '';
1003 $field_id = sprintf( '%s_%s', $args['id'], $value );
1004
1005 echo sprintf( '<li><label><input type="checkbox" name="%s[]" id="%s" value="%s" class="%s" %s> %s</label></li>', esc_attr( $args['name'] ), esc_attr( $field_id ), esc_html( $value ), esc_attr( $args['class'] ), esc_html( $checked ), esc_html( $text ) );
1006 }
1007
1008 echo '</ul>';
1009
1010 $this->generate_description( $args );
1011 }
1012
1013 /**
1014 * Generate: Color field
1015 *
1016 * @param array $args Field arguments.
1017 */
1018 public function generate_color_field( $args ) {
1019 $color_picker_id = sprintf( '%s_cp', $args['id'] );
1020 $args['value'] = esc_attr( stripslashes( $args['value'] ) );
1021
1022 echo '<div style="position:relative;">';
1023
1024 echo sprintf( '<input type="text" name="%s" id="%s" value="%s" class="%s">', esc_attr( $args['name'] ), esc_attr( $args['id'] ), esc_attr( $args['value'] ), esc_attr( $args['class'] ) );
1025
1026 echo sprintf( '<div id="%s" style="position:absolute;top:0;left:190px;background:#fff;z-index:9999;"></div>', esc_attr( $color_picker_id ) );
1027
1028 $this->generate_description( $args );
1029
1030 echo '<script type="text/javascript">
1031 jQuery(document).ready(function($){
1032 var colorPicker = $("#' . esc_attr( $color_picker_id ) . '");
1033 colorPicker.farbtastic("#' . esc_attr( $args['id'] ) . '");
1034 colorPicker.hide();
1035 $("#' . esc_attr( $args['id'] ) . '").on("focus", function(){
1036 colorPicker.show();
1037 });
1038 $("#' . esc_attr( $args['id'] ) . '").on("blur", function(){
1039 colorPicker.hide();
1040 if($(this).val() == "") $(this).val("#");
1041 });
1042 });
1043 </script>';
1044
1045 echo '</div>';
1046 }
1047
1048 /**
1049 * Generate: File field
1050 *
1051 * @param array $args Field arguments.
1052 */
1053 public function generate_file_field( $args ) {
1054 $args['value'] = esc_attr( $args['value'] );
1055 $button_id = sprintf( '%s_button', $args['id'] );
1056
1057 /**
1058 * Hook in to generate a file preview e.g. image thumbnail.
1059 */
1060 do_action( 'wpsf_file_field_preview', $args['value'], $args );
1061
1062 echo sprintf( '<input type="text" name="%s" id="%s" value="%s" class="regular-text %s"> ', esc_attr( $args['name'] ), esc_attr( $args['id'] ), esc_html( $args['value'] ), esc_attr( $args['class'] ) );
1063
1064 echo sprintf( '<input type="button" class="button wpsf-browse" id="%s" value="%s" />', esc_attr( $button_id ), esc_html__( 'Browse', 'wpsf' ) );
1065
1066 $this->generate_description( $args );
1067 ?>
1068 <script type='text/javascript'>
1069 jQuery( document ).ready( function( $ ) {
1070
1071 // Uploading files
1072 var file_frame;
1073 var wp_media_post_id = wp.media.model.settings.post.id; // Store the old id.
1074 var set_to_post_id = 0;
1075
1076 jQuery( document.body ).on('click', '#<?php echo esc_attr( $button_id ); ?>', function( event ){
1077
1078 event.preventDefault();
1079
1080 // If the media frame already exists, reopen it.
1081 if ( file_frame ) {
1082 // Set the post ID to what we want
1083 file_frame.uploader.uploader.param( 'post_id', set_to_post_id );
1084 // Open frame
1085 file_frame.open();
1086 return;
1087 } else {
1088 // Set the wp.media post id so the uploader grabs the ID we want when initialised.
1089 wp.media.model.settings.post.id = set_to_post_id;
1090 }
1091
1092 // Create the media frame.
1093 file_frame = wp.media.frames.file_frame = wp.media({
1094 title: '<?php echo esc_html__( 'Select a image to upload', 'wpsf' ); ?>',
1095 button: {
1096 text: '<?php echo esc_html__( 'Use this image', 'wpsf' ); ?>',
1097 },
1098 multiple: false // Set to true to allow multiple files to be selected
1099 });
1100
1101 // When an image is selected, run a callback.
1102 file_frame.on( 'select', function() {
1103 // We set multiple to false so only get one image from the uploader
1104 attachment = file_frame.state().get('selection').first().toJSON();
1105
1106 // Do something with attachment.id and/or attachment.url here
1107 $( '#image-preview' ).attr( 'src', attachment.url ).css( 'width', 'auto' );
1108 $( '#image_attachment_id' ).val( attachment.id );
1109 $( '#<?php echo esc_attr( $args['id'] ); ?>' ).val( attachment.url );
1110
1111 // Restore the main post ID
1112 wp.media.model.settings.post.id = wp_media_post_id;
1113 });
1114
1115 // Finally, open the modal
1116 file_frame.open();
1117 });
1118
1119 // Restore the main ID when the add media button is pressed
1120 jQuery( 'a.add_media' ).on( 'click', function() {
1121 wp.media.model.settings.post.id = wp_media_post_id;
1122 });
1123 });
1124 </script>
1125 <?php
1126 }
1127
1128 /**
1129 * Generate: Editor field
1130 *
1131 * @param array $args Field arguments.
1132 */
1133 public function generate_editor_field( $args ) {
1134 $settings = ( isset( $args['editor_settings'] ) && is_array( $args['editor_settings'] ) ) ? $args['editor_settings'] : array();
1135 $settings['textarea_name'] = $args['name'];
1136
1137 wp_editor( $args['value'], $args['id'], $settings );
1138
1139 $this->generate_description( $args );
1140 }
1141
1142 /**
1143 * Generate: Code editor field
1144 *
1145 * @param array $args Field arguments.
1146 */
1147 public function generate_code_editor_field( $args ) {
1148 printf(
1149 '<textarea
1150 name="%s"
1151 id="%s"
1152 placeholder="%s"
1153 rows="5"
1154 cols="60"
1155 class="%s"
1156 >%s</textarea>',
1157 esc_attr( $args['name'] ),
1158 esc_attr( $args['id'] ),
1159 esc_attr( $args['placeholder'] ),
1160 esc_attr( $args['class'] ),
1161 esc_html( $args['value'] )
1162 );
1163
1164 $settings = wp_enqueue_code_editor( array( 'type' => esc_attr( $args['mimetype'] ) ) );
1165
1166 wp_add_inline_script(
1167 'code-editor',
1168 sprintf(
1169 'jQuery( function() { wp.codeEditor.initialize( "%s", %s ); } );',
1170 esc_attr( $args['id'] ),
1171 wp_json_encode( $settings )
1172 )
1173 );
1174
1175 $this->generate_description( $args );
1176 }
1177
1178 /**
1179 * Generate: Custom field
1180 *
1181 * @param array $args Field arguments.
1182 */
1183 public function generate_custom_field( $args ) {
1184 if ( isset( $args['output'] ) && is_callable( $args['output'] ) ) {
1185 call_user_func( $args['output'], $args );
1186 return;
1187 }
1188
1189 // @codingStandardsIgnoreStart
1190 echo ( isset( $args['output'] ) ) ? $args['output'] : $args['default']; // This output isn't easily escaped.
1191 // @codingStandardsIgnoreEnd
1192 }
1193
1194 /**
1195 * Generate: Multi Inputs field
1196 *
1197 * @param array $args Field arguments.
1198 */
1199 public function generate_multiinputs_field( $args ) {
1200 $field_titles = array_keys( $args['default'] );
1201 $values = array_values( $args['value'] );
1202
1203 echo '<div class="wpsf-multifields">';
1204
1205 $i = 0;
1206 $c = count( $values );
1207 while ( $i < $c ) :
1208
1209 $field_id = sprintf( '%s_%s', $args['id'], $i );
1210 $value = esc_attr( stripslashes( $values[ $i ] ) );
1211
1212 echo '<div class="wpsf-multifields__field">';
1213 echo '<input type="text" name="' . esc_attr( $args['name'] ) . '[]" id="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" class="regular-text ' . esc_attr( $args['class'] ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
1214 echo '<br><span>' . esc_html( $field_titles[ $i ] ) . '</span>';
1215 echo '</div>';
1216
1217 $i ++;
1218 endwhile;
1219
1220 echo '</div>';
1221
1222 $this->generate_description( $args );
1223 }
1224
1225 /**
1226 * Generate: Field ID
1227 *
1228 * @param mixed $id Field ID.
1229 *
1230 * @return string
1231 */
1232 public function generate_field_name( $id ) {
1233 return sprintf( '%s_settings[%s]', $this->option_group, $id );
1234 }
1235
1236 /**
1237 * Generate: Description
1238 *
1239 * @param mixed $description Field description.
1240 */
1241 public function generate_description( $args ) {
1242 $classes = 'wpsf-description';
1243 $description = ( ! empty( $args['desc'] ) ) ? $args['desc'] : false;
1244 $descriptions = array();
1245
1246 // Add the main description.
1247 if ( $description ) {
1248 $descriptions[] = array(
1249 'classes' => $classes,
1250 // Serialize group field data to prevent errors.
1251 'value' => ( is_array( $args['value'] ) ) ? serialize( $args['value'] ) : $args['value'],
1252 'description' => $description,
1253 );
1254 }
1255
1256 // Output any conditional descriptions that exist.
1257 if ( 'select' === $args['type'] && ! empty( $args['conditional_desc'] ) && is_array( $args['conditional_desc'] ) ) {
1258
1259 foreach ( $args['conditional_desc'] as $value => $conditional_description ) {
1260
1261 if ( $conditional_description ) {
1262 // Add a class to hide descriptions for other values.
1263 if ( $args['value'] !== $value ) {
1264 $classes .= ' wpsf-hide-description';
1265 }
1266
1267 $descriptions[] = array(
1268 'classes' => $classes,
1269 'value' => $value,
1270 'description' => $conditional_description,
1271 );
1272 }
1273 }
1274 }
1275
1276 // Output all descriptions.
1277 foreach ( $descriptions as $description_data ) {
1278 printf(
1279 '<p class="%s" data-value="%s">%s</p>',
1280 esc_attr( $description_data['classes'] ),
1281 esc_attr( $description_data['value'] ),
1282 wp_kses_post( $description_data['description'] )
1283 );
1284 }
1285 }
1286
1287 /**
1288 * Output the settings form
1289 */
1290 public function settings() {
1291 /**
1292 * Hook: execute callback before the settings form for a given group.
1293 *
1294 * @hook wpsf_before_settings_<option_group>
1295 * @since 1.6.9
1296 */
1297 do_action( 'wpsf_before_settings_' . $this->option_group );
1298 ?>
1299 <form action="options.php" method="post" novalidate enctype="multipart/form-data">
1300 <?php
1301 /**
1302 * Hook: execute callback before the settings fields for a given group.
1303 *
1304 * @hook wpsf_before_settings_fields_<option_group>
1305 * @since 1.6.9
1306 */
1307 do_action( 'wpsf_before_settings_fields_' . $this->option_group );
1308 ?>
1309 <?php settings_fields( $this->option_group ); ?>
1310
1311 <?php
1312 /**
1313 * Hook: execute callback to output the settings sections for a given group.
1314 *
1315 * @hook wpsf_do_settings_sections_<option_group>
1316 * @since 1.6.9
1317 */
1318 do_action( 'wpsf_do_settings_sections_' . $this->option_group );
1319 ?>
1320
1321 <?php
1322 /**
1323 * Filter: control whether the save changes button should be visible or not for a given option group.
1324 *
1325 * @filter wpsf_show_save_changes_button_<option_group>
1326 * @since 1.6.9
1327 * @param boolean
1328 */
1329 if ( apply_filters( 'wpsf_show_save_changes_button_' . $this->option_group, true ) ) {
1330 ?>
1331 <p class="submit">
1332 <input type="submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" />
1333 </p>
1334 <?php } ?>
1335 </form>
1336 <?php
1337 /**
1338 * Hook: execute callback after the settings form for a given group.
1339 *
1340 * @hook wpsf_after_settings_<option_group>
1341 * @since 1.6.9
1342 */
1343 do_action( 'wpsf_after_settings_' . $this->option_group );
1344 }
1345
1346 /**
1347 * Helper: Get Settings
1348 *
1349 * @return array
1350 */
1351 public function get_settings() {
1352 $settings_name = $this->option_group . '_settings';
1353
1354 static $settings = array();
1355
1356 if ( isset( $settings[ $settings_name ] ) ) {
1357 return $settings[ $settings_name ];
1358 }
1359
1360 $saved_settings = get_option( $this->option_group . '_settings' );
1361 $settings[ $settings_name ] = array();
1362
1363 if ( ! $this->settings ) {
1364 return $settings[ $settings_name ];
1365 }
1366
1367 foreach ( $this->settings as $section ) {
1368 if ( empty( $section['fields'] ) ) {
1369 continue;
1370 }
1371
1372 foreach ( $section['fields'] as $field ) {
1373 if ( ! empty( $field['default'] ) && is_array( $field['default'] ) ) {
1374 $field['default'] = array_values( $field['default'] );
1375 }
1376
1377 // If a field name override has been provided, use it.
1378 if ( ! empty( $field['name'] ) ) {
1379 $setting_key = $field['name'];
1380 } else {
1381 $setting_key = ( $this->has_tabs() ) ? sprintf( '%s_%s_%s', $section['tab_id'], $section['section_id'], $field['id'] ) : sprintf( '%s_%s', $section['section_id'], $field['id'] );
1382 }
1383
1384 if ( isset( $saved_settings[ $setting_key ] ) ) {
1385 $settings[ $settings_name ][ $setting_key ] = $saved_settings[ $setting_key ];
1386 } else {
1387 $settings[ $settings_name ][ $setting_key ] = ( isset( $field['default'] ) ) ? $field['default'] : false;
1388 }
1389 }
1390 }
1391
1392 return $settings[ $settings_name ];
1393 }
1394
1395 /**
1396 * Tabless Settings sections
1397 */
1398 public function do_tabless_settings_sections() {
1399 ?>
1400 <div class="wpsf-section wpsf-tabless">
1401 <?php do_settings_sections( $this->option_group ); ?>
1402 </div>
1403 <?php
1404 }
1405
1406 /**
1407 * Tabbed Settings sections
1408 */
1409 public function do_tabbed_settings_sections() {
1410 $i = 0;
1411 foreach ( $this->tabs as $tab_data ) {
1412 ?>
1413 <div id="tab-<?php echo esc_attr( $tab_data['id'] ); ?>" class="wpsf-section wpsf-tab wpsf-tab--<?php echo esc_attr( $tab_data['id'] ); ?> <?php
1414 if ( 0 === $i ) {
1415 echo 'wpsf-tab--active';
1416 }
1417 ?>
1418 ">
1419 <div class="postbox">
1420 <?php do_settings_sections( sprintf( '%s_%s', $this->option_group, $tab_data['id'] ) ); ?>
1421 </div>
1422 </div>
1423 <?php
1424 $i ++;
1425 }
1426 }
1427
1428 /**
1429 * Output the tab links
1430 */
1431 public function tab_links() {
1432 /**
1433 * Filter: control whether the tab links should be visible or not for a given option group.
1434 *
1435 * @filter wpsf_show_tab_links_<option_group>
1436 * @since 1.6.9
1437 * @param boolean
1438 */
1439 if ( ! apply_filters( 'wpsf_show_tab_links_' . $this->option_group, true ) ) {
1440 return;
1441 }
1442
1443 /**
1444 * Hook: execute callback before the tab links for a given option group.
1445 *
1446 * @hook wpsf_before_tab_links_<option_group>
1447 * @since 1.6.9
1448 */
1449 do_action( 'wpsf_before_tab_links_' . $this->option_group );
1450 ?>
1451 <ul class="wpsf-nav">
1452 <?php
1453 $i = 0;
1454 foreach ( $this->tabs as $tab_data ) {
1455 if ( ! $this->tab_has_settings( $tab_data['id'] ) ) {
1456 continue;
1457 }
1458
1459 if ( ! isset( $tab_data['class'] ) ) {
1460 $tab_data['class'] = '';
1461 }
1462
1463 $tab_data['class'] .= self::add_show_hide_classes( $tab_data );
1464
1465 $active = ( 0 === $i ) ? 'wpsf-nav__item--active' : '';
1466 ?>
1467 <li class="wpsf-nav__item <?php echo esc_attr( $active ); ?>">
1468 <a class="wpsf-nav__item-link <?php echo esc_attr( $tab_data['class'] ); ?>" href="#tab-<?php echo esc_attr( $tab_data['id'] ); ?>"><?php echo wp_kses_post( $tab_data['title'] ); ?></a>
1469 </li>
1470 <?php
1471 $i ++;
1472 }
1473 ?>
1474 <li class="wpsf-nav__item wpsf-nav__item--last">
1475 <input type="submit" class="button-primary wpsf-button-submit" value="<?php esc_attr_e( 'Save Changes' ); ?>">
1476 </li>
1477 </ul>
1478
1479 <?php // Add this here so notices are moved. ?>
1480 <div class="wrap wpsf-notices"><h2>&nbsp;</h2></div>
1481 <?php
1482 /**
1483 * Hook: execute callback after the tab links for a given option group.
1484 *
1485 * @hook wpsf_after_tab_links_<option_group>
1486 * @since 1.6.9
1487 */
1488 do_action( 'wpsf_after_tab_links_' . $this->option_group );
1489 }
1490
1491 /**
1492 * Does this tab have settings?
1493 *
1494 * @param string $tab_id Tab ID.
1495 *
1496 * @return bool
1497 */
1498 public function tab_has_settings( $tab_id ) {
1499 if ( empty( $this->settings ) ) {
1500 return false;
1501 }
1502
1503 foreach ( $this->settings as $settings_section ) {
1504 if ( $tab_id !== $settings_section['tab_id'] ) {
1505 continue;
1506 }
1507
1508 return true;
1509 }
1510
1511 return false;
1512 }
1513
1514 /**
1515 * Check if this settings instance has tabs
1516 */
1517 public function has_tabs() {
1518 if ( ! empty( $this->tabs ) ) {
1519 return true;
1520 }
1521
1522 return false;
1523 }
1524
1525 /**
1526 * Add Show Hide Classes.
1527 *
1528 * @param array $args Field arguments.
1529 * @param string $type Type.
1530 */
1531 public static function add_show_hide_classes( $args, $type = 'show_if' ) {
1532 $class = '';
1533 $slug = ' ' . str_replace( '_', '-', $type );
1534 if ( isset( $args[ $type ] ) && is_array( $args[ $type ] ) ) {
1535 $class .= $slug;
1536 foreach ( $args[ $type ] as $condition ) {
1537 if ( isset( $condition['field'] ) && $condition['value'] ) {
1538 $value_string = '';
1539 foreach ( $condition['value'] as $value ) {
1540 if ( ! empty( $value_string ) ) {
1541 $value_string .= '||';
1542 }
1543 $value_string .= $value;
1544 }
1545
1546 if ( ! empty( $value_string ) ) {
1547 $class .= $slug . '--' . $condition['field'] . '===' . $value_string;
1548 }
1549 } else {
1550 $and_string = '';
1551 foreach ( $condition as $and_condition ) {
1552 if ( ! isset( $and_condition['field'] ) || ! isset( $and_condition['value'] ) ) {
1553 continue;
1554 }
1555
1556 if ( ! empty( $and_string ) ) {
1557 $and_string .= '&&';
1558 }
1559
1560 $value_string = '';
1561 foreach ( $and_condition['value'] as $value ) {
1562 if ( ! empty( $value_string ) ) {
1563 $value_string .= '||';
1564 }
1565 $value_string .= $value;
1566 }
1567
1568 if ( ! empty( $value_string ) ) {
1569 $and_string .= $and_condition['field'] . '===' . $value_string;
1570 }
1571 }
1572
1573 if ( ! empty( $and_string ) ) {
1574 $class .= $slug . '--' . $and_string;
1575 }
1576 }
1577 }
1578 }
1579
1580 // Run the function again with hide if.
1581 if ( 'hide_if' !== $type ) {
1582 $class .= self::add_show_hide_classes( $args, 'hide_if' );
1583 }
1584
1585 return $class;
1586 }
1587
1588 /**
1589 * Handle export settings action.
1590 */
1591 public static function export_settings() {
1592 $_wpnonce = filter_input( INPUT_GET, '_wpnonce' );
1593 $option_group = filter_input( INPUT_GET, 'option_group' );
1594
1595 if ( empty( $_wpnonce ) || ! wp_verify_nonce( $_wpnonce, 'wpsf_export_settings' ) ) {
1596 wp_die( esc_html__( 'Action failed.', 'wpsf' ) );
1597 }
1598
1599 if ( empty( $option_group ) ) {
1600 wp_die( esc_html__( 'No option group specified.', 'wpsf' ) );
1601 }
1602
1603 $options = get_option( $option_group . '_settings' );
1604
1605 header( 'Content-Disposition: attachment; filename=wpsf-settings-' . $option_group . '.json' );
1606
1607 wp_send_json( $options );
1608 }
1609
1610 /**
1611 * Import settings.
1612 */
1613 public function import_settings() {
1614 $_wpnonce = filter_input( INPUT_POST, '_wpnonce' );
1615 $option_group = filter_input( INPUT_POST, 'option_group' );
1616 $settings = filter_input( INPUT_POST, 'settings' );
1617
1618 if ( $option_group !== $this->option_group ) {
1619 return;
1620 }
1621
1622 // verify nonce.
1623 if ( empty( $_wpnonce ) || ! wp_verify_nonce( $_wpnonce, 'wpsf_import_settings' ) ) {
1624 wp_send_json_error();
1625 }
1626
1627 // check if $settings is a valid json.
1628 if ( ! is_string( $settings ) || ! is_array( json_decode( $settings, true ) ) ) {
1629 wp_send_json_error();
1630 }
1631
1632 $settings_data = json_decode( $settings, true );
1633 update_option( $option_group . '_settings', $settings_data );
1634
1635 wp_send_json_success();
1636 }
1637
1638 /**
1639 * Helper: Array to HTML Attributes
1640 */
1641 public static function array_to_html_atts( $array = array() ) {
1642 if ( ! is_array( $array ) || empty( $array ) ) {
1643 return false;
1644 }
1645
1646 $return = '';
1647
1648 foreach ( $array as $key => $value ) {
1649 if ( '' === $value ) {
1650 continue;
1651 }
1652
1653 $return .= sprintf( '%s="%s" ', $key, esc_attr( $value ) );
1654 }
1655
1656 return $return;
1657 }
1658 }
1659 }
1660
1661 if ( ! function_exists( 'wpsf_get_setting' ) ) {
1662 /**
1663 * Get a setting from an option group
1664 *
1665 * @param string $option_group Option group.
1666 * @param string $section_id May also be prefixed with tab ID.
1667 * @param string $field_id Field ID.
1668 *
1669 * @return mixed
1670 */
1671 function wpsf_get_setting( $option_group, $section_id, $field_id ) {
1672 $options = get_option( $option_group . '_settings' );
1673 if ( isset( $options[ $section_id . '_' . $field_id ] ) ) {
1674 return $options[ $section_id . '_' . $field_id ];
1675 }
1676
1677 return false;
1678 }
1679 }
1680
1681 if ( ! function_exists( 'wpsf_delete_settings' ) ) {
1682 /**
1683 * Delete all the saved settings from a settings file/option group
1684 *
1685 * @param string $option_group Option group.
1686 */
1687 function wpsf_delete_settings( $option_group ) {
1688 delete_option( $option_group . '_settings' );
1689 }
1690 }
1691