PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 2.4.12
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v2.4.12
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / admin / views / sp-framework / classes / options.class.php

options.class.php in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 2.4.12, at admin/views/sp-framework/classes/options.class.php

875 lines 26.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if ( ! defined( 'ABSPATH' ) ) {
2 die; } // Cannot access directly.
3
4 if ( ! class_exists( 'SP_PC_Options' ) ) {
5 /**
6 * Options Class
7 *
8 * @since 1.0.0
9 * @version 1.0.0
10 */
11 class SP_PC_Options extends SP_PC_Abstract {
12
13 /**
14 * Unique ID/Name
15 *
16 * @var string
17 */
18 public $unique = '';
19 /**
20 * Notice.
21 *
22 * @var string
23 */
24 public $notice = '';
25 /**
26 * Abstract.
27 *
28 * @var string
29 */
30 public $abstract = 'options';
31 /**
32 * Setions.
33 *
34 * @var array
35 */
36 public $sections = array();
37 /**
38 * Options
39 *
40 * @var array
41 */
42 public $options = array();
43
44 /**
45 * Errors.
46 *
47 * @var array
48 */
49 public $errors = array();
50
51 /**
52 * Pre tabs.
53 *
54 * @var array
55 */
56 public $pre_tabs = array();
57
58 /**
59 * Pre fields.
60 *
61 * @var array
62 */
63 public $pre_fields = array();
64
65 /**
66 * Pre sections.
67 *
68 * @var array
69 */
70 public $pre_sections = array();
71
72 /**
73 * Default arguments.
74 *
75 * @var array
76 */
77 public $args = array(
78
79 // framework title.
80 'framework_title' => 'SPF Framework <small>by SP</small>',
81 'framework_class' => '',
82
83 // menu settings.
84 'menu_title' => '',
85 'menu_slug' => '',
86 'menu_type' => 'menu',
87 // 'menu_capability' => 'manage_options', It's implemented in add_admin_menu()
88 'menu_icon' => null,
89 'menu_position' => null,
90 'menu_hidden' => false,
91 'menu_parent' => '',
92
93 // menu extras.
94 'show_bar_menu' => true,
95 'show_sub_menu' => true,
96 'show_network_menu' => true,
97 'show_in_customizer' => false,
98
99 'show_search' => true,
100 'show_reset_all' => true,
101 'show_reset_section' => true,
102 'show_footer' => true,
103 'show_all_options' => true,
104 'sticky_header' => true,
105 'save_defaults' => true,
106 'ajax_save' => true,
107
108 // admin bar menu settings.
109 'admin_bar_menu_icon' => '',
110 'admin_bar_menu_priority' => 80,
111
112 // footer.
113 'footer_text' => '',
114 'footer_after' => '',
115 'footer_credit' => '',
116
117 // database model.
118 'database' => '', // options, transient, theme_mod, network.
119 'transient_time' => 0,
120
121 // contextual help.
122 'contextual_help' => array(),
123 'contextual_help_sidebar' => '',
124
125 // typography options.
126 'enqueue_webfont' => true,
127 'async_webfont' => false,
128
129 // others.
130 'output_css' => true,
131
132 // theme.
133 'theme' => 'dark',
134
135 'class' => '',
136
137 // external default values.
138 'defaults' => array(),
139
140 );
141
142 /**
143 * Run framework construct.
144 *
145 * @param string $key The filter unique key.
146 * @param array $params The parameters.
147 */
148 public function __construct( $key, $params = array() ) {
149
150 $this->unique = $key;
151 $this->args = apply_filters( "spf_{$this->unique}_args", wp_parse_args( $params['args'], $this->args ), $this );
152 $this->sections = apply_filters( "spf_{$this->unique}_sections", $params['sections'], $this );
153
154 // run only is admin panel options, avoid performance loss.
155 $this->pre_tabs = $this->pre_tabs( $this->sections );
156 $this->pre_fields = $this->pre_fields( $this->sections );
157 $this->pre_sections = $this->pre_sections( $this->sections );
158
159 $this->get_options();
160 $this->set_options();
161 $this->save_defaults();
162
163 add_action( 'admin_menu', array( &$this, 'add_admin_menu' ) );
164 add_action( 'admin_bar_menu', array( &$this, 'add_admin_bar_menu' ), $this->args['admin_bar_menu_priority'] );
165 add_action( 'wp_ajax_spf_' . $this->unique . '_ajax_save', array( &$this, 'ajax_save' ) );
166
167 if ( ! empty( $this->args['show_network_menu'] ) ) {
168 add_action( 'network_admin_menu', array( &$this, 'add_admin_menu' ) );
169 }
170
171 // wp enqeueu for typography and output css.
172 parent::__construct();
173
174 }
175
176 /**
177 * Instance.
178 *
179 * @param object $key The instance key.
180 * @param array $params All the parameters.
181 * @return mixed
182 */
183 public static function instance( $key, $params = array() ) {
184 return new self( $key, $params );
185 }
186 /**
187 * Pre tabs.
188 *
189 * @param array $sections All the sections.
190 * @return mixed
191 */
192 public function pre_tabs( $sections ) {
193
194 $result = array();
195 $parents = array();
196 $count = 100;
197
198 foreach ( $sections as $key => $section ) {
199 if ( ! empty( $section['parent'] ) ) {
200 $section['priority'] = ( isset( $section['priority'] ) ) ? $section['priority'] : $count;
201 $parents[ $section['parent'] ][] = $section;
202 unset( $sections[ $key ] );
203 }
204 $count++;
205 }
206
207 foreach ( $sections as $key => $section ) {
208 $section['priority'] = ( isset( $section['priority'] ) ) ? $section['priority'] : $count;
209 if ( ! empty( $section['id'] ) && ! empty( $parents[ $section['id'] ] ) ) {
210 $section['subs'] = wp_list_sort( $parents[ $section['id'] ], array( 'priority' => 'ASC' ), 'ASC', true );
211 }
212 $result[] = $section;
213 $count++;
214 }
215
216 return wp_list_sort( $result, array( 'priority' => 'ASC' ), 'ASC', true );
217 }
218
219 /**
220 * Pre fields method.
221 *
222 * @param array $sections The sections.
223 * @return $result
224 */
225 public function pre_fields( $sections ) {
226
227 $result = array();
228
229 foreach ( $sections as $key => $section ) {
230 if ( ! empty( $section['fields'] ) ) {
231 foreach ( $section['fields'] as $field ) {
232 $result[] = $field;
233 }
234 }
235 }
236
237 return $result;
238 }
239
240 /**
241 * The pre sections.
242 *
243 * @param array $sections The sections.
244 * @return mixed
245 */
246 public function pre_sections( $sections ) {
247
248 $result = array();
249
250 foreach ( $this->pre_tabs as $tab ) {
251 if ( ! empty( $tab['subs'] ) ) {
252 foreach ( $tab['subs'] as $sub ) {
253 $result[] = $sub;
254 }
255 }
256 if ( empty( $tab['subs'] ) ) {
257 $result[] = $tab;
258 }
259 }
260
261 return $result;
262 }
263
264 /**
265 * Add admin bar menu.
266 *
267 * @param object $wp_admin_bar The admin bar.
268 * @return void
269 */
270 public function add_admin_bar_menu( $wp_admin_bar ) {
271
272 if ( ! empty( $this->args['show_bar_menu'] ) && empty( $this->args['menu_hidden'] ) ) {
273
274 global $submenu;
275
276 $menu_slug = $this->args['menu_slug'];
277 $menu_icon = ( ! empty( $this->args['admin_bar_menu_icon'] ) ) ? '<span class="spf-ab-icon ab-icon ' . $this->args['admin_bar_menu_icon'] . '"></span>' : '';
278
279 $wp_admin_bar->add_node(
280 array(
281 'id' => $menu_slug,
282 'title' => $menu_icon . $this->args['menu_title'],
283 'href' => ( is_network_admin() ) ? network_admin_url( 'admin.php?page=' . $menu_slug ) : admin_url( 'admin.php?page=' . $menu_slug ),
284 )
285 );
286
287 if ( ! empty( $submenu[ $menu_slug ] ) ) {
288 foreach ( $submenu[ $menu_slug ] as $key => $menu ) {
289 $wp_admin_bar->add_node(
290 array(
291 'parent' => $menu_slug,
292 'id' => $menu_slug . '-' . $key,
293 'title' => $menu[0],
294 'href' => ( is_network_admin() ) ? network_admin_url( 'admin.php?page=' . $menu[2] ) : admin_url( 'admin.php?page=' . $menu[2] ),
295 )
296 );
297 }
298 }
299
300 if ( ! empty( $this->args['show_network_menu'] ) ) {
301 $wp_admin_bar->add_node(
302 array(
303 'parent' => 'network-admin',
304 'id' => $menu_slug . '-network-admin',
305 'title' => $menu_icon . $this->args['menu_title'],
306 'href' => network_admin_url( 'admin.php?page=' . $menu_slug ),
307 )
308 );
309 }
310 }
311
312 }
313
314 /**
315 * Ajax save method.
316 *
317 * @return void
318 */
319 public function ajax_save() {
320
321 $result = $this->set_options( true );
322 if ( ! $result ) {
323 wp_send_json_error(
324 array(
325 'success' => false,
326 'error' => esc_html__(
327 'Error while saving.',
328 'post-carousel'
329 ),
330 )
331 );
332
333 } else {
334 wp_send_json_success(
335 array(
336 'success' => true,
337 'notice' => $this->notice,
338 'errors' => $this->errors,
339 )
340 );
341 }
342 }
343
344 /**
345 * Get default value.
346 *
347 * @param array $field The field array.
348 * @param array $options The options array.
349 * @return mixed
350 */
351 public function get_default( $field, $options = array() ) {
352
353 $default = ( isset( $this->args['defaults'][ $field['id'] ] ) ) ? $this->args['defaults'][ $field['id'] ] : '';
354 $default = ( isset( $field['default'] ) ) ? $field['default'] : $default;
355 $default = ( isset( $options[ $field['id'] ] ) ) ? $options[ $field['id'] ] : $default;
356
357 return $default;
358
359 }
360
361 /**
362 * Save defaults and set new fields value to main options.
363 *
364 * @return void
365 */
366 public function save_defaults() {
367
368 $tmp_options = $this->options;
369
370 foreach ( $this->pre_fields as $field ) {
371 if ( ! empty( $field['id'] ) ) {
372 $this->options[ $field['id'] ] = $this->get_default( $field, $this->options );
373 }
374 }
375
376 if ( $this->args['save_defaults'] && empty( $tmp_options ) ) {
377 $this->save_options( $this->options );
378 }
379
380 }
381
382 /**
383 * Set options.
384 *
385 * @param boolean $ajax The ajax save.
386 *
387 * @return mixed
388 */
389 public function set_options( $ajax = false ) {
390
391 // XSS ok.
392 // No worries, This "POST" requests is sanitizing in the below foreach. see #L380 - #L384.
393 $response = ( $ajax && ! empty( $_POST['data'] ) ) ? json_decode( wp_unslash( trim( $_POST['data'] ) ), true ) : $_POST; // phpcs:ignore
394
395 // Set variables.
396 $data = array();
397 $noncekey = 'spf_options_nonce' . $this->unique;
398 $nonce = ( ! empty( $response[ $noncekey ] ) ) ? $response[ $noncekey ] : '';
399 $options = ( ! empty( $response[ $this->unique ] ) ) ? $response[ $this->unique ] : array();
400 $transient = ( ! empty( $response['spf_transient'] ) ) ? $response['spf_transient'] : array();
401
402 if ( wp_verify_nonce( $nonce, 'spf_options_nonce' ) ) {
403
404 $importing = false;
405 $section_id = ( ! empty( $transient['section'] ) ) ? $transient['section'] : '';
406
407 // import data.
408 if ( ! $ajax && ! empty( $response['spf_import_data'] ) ) {
409
410 // XSS ok.
411 // No worries, This "POST" requests is sanitizing in the below foreach. see #L380 - #L384.
412 $import_data = json_decode( wp_unslash( trim( $response['spf_import_data'] ) ), true );
413 $options = ( is_array( $import_data ) && ! empty( $import_data ) ) ? $import_data : array();
414 $importing = true;
415 $this->notice = esc_html__( 'Settings successfully imported.', 'post-carousel' );
416
417 }
418
419 if ( ! empty( $transient['reset'] ) ) {
420
421 foreach ( $this->pre_fields as $field ) {
422 if ( ! empty( $field['id'] ) ) {
423 $data[ $field['id'] ] = $this->get_default( $field );
424 }
425 }
426
427 $this->notice = esc_html__( 'Default options restored.', 'post-carousel' );
428
429 } elseif ( ! empty( $transient['reset_section'] ) && ! empty( $section_id ) ) {
430
431 if ( ! empty( $this->pre_sections[ $section_id - 1 ]['fields'] ) ) {
432
433 foreach ( $this->pre_sections[ $section_id - 1 ]['fields'] as $field ) {
434 if ( ! empty( $field['id'] ) ) {
435 $data[ $field['id'] ] = $this->get_default( $field );
436 }
437 }
438 }
439
440 $data = wp_parse_args( $data, $this->options );
441 $this->notice = esc_html__( 'Default options restored for only this section.', 'post-carousel' );
442
443 } else {
444
445 // sanitize and validate.
446 foreach ( $this->pre_fields as $field ) {
447
448 if ( ! empty( $field['id'] ) ) {
449
450 $field_id = $field['id'];
451 $field_value = isset( $options[ $field_id ] ) ? $options[ $field_id ] : '';
452
453 // Ajax and Importing doing wp_unslash already.
454 if ( ! $ajax && ! $importing ) {
455 $field_value = wp_unslash( $field_value );
456 }
457
458 // sanitize.
459 if ( ! isset( $field['sanitize'] ) ) {
460 if ( is_array( $field_value ) ) {
461
462 $data[ $field_id ] = wp_kses_post_deep( $field_value );
463
464 } else {
465
466 $data[ $field_id ] = wp_kses_post( $field_value );
467 }
468 } elseif ( isset( $field['sanitize'] ) && is_callable( $field['sanitize'] ) ) {
469
470 $data[ $field_id ] = call_user_func( $field['sanitize'], $field_value );
471
472 } else {
473 $data[ $field_id ] = $field_value;
474
475 }
476
477 // Validate "post" request of field.
478 if ( isset( $field['validate'] ) && is_callable( $field['validate'] ) ) {
479
480 $has_validated = call_user_func( $field['validate'], $field_value );
481
482 if ( ! empty( $has_validated ) ) {
483 $data[ $field_id ] = ( isset( $this->options[ $field_id ] ) ) ? $this->options[ $field_id ] : '';
484 $this->errors[ $field_id ] = $has_validated;
485 }
486 }
487 }
488 }
489 }
490
491 $data = apply_filters( "spf_{$this->unique}_save", $data, $this );
492
493 do_action( "spf_{$this->unique}_save_before", $data, $this );
494
495 $this->options = $data;
496
497 $this->save_options( $data );
498
499 do_action( "spf_{$this->unique}_save_after", $data, $this );
500
501 if ( empty( $this->notice ) ) {
502 $this->notice = esc_html__( 'Settings saved.', 'post-carousel' );
503 }
504
505 return true;
506 }
507
508 return false;
509
510 }
511
512 /**
513 * Save options database.
514 *
515 * @param array $data The options values.
516 * @return void
517 */
518 public function save_options( $data ) {
519
520 if ( 'transient' === $this->args['database'] ) {
521 set_transient( $this->unique, $data, $this->args['transient_time'] );
522 } elseif ( 'theme_mod' === $this->args['database'] ) {
523 set_theme_mod( $this->unique, $data );
524 } elseif ( 'network' === $this->args['database'] ) {
525 update_site_option( $this->unique, $data );
526 } else {
527 update_option( $this->unique, $data );
528 }
529
530 do_action( "spf_{$this->unique}_saved", $data, $this );
531
532 }
533
534 /**
535 * Get options from database.
536 *
537 * @return mixed
538 */
539 public function get_options() {
540
541 if ( 'transient' === $this->args['database'] ) {
542 $this->options = get_transient( $this->unique );
543 } elseif ( 'theme_mod' === $this->args['database'] ) {
544 $this->options = get_theme_mod( $this->unique );
545 } elseif ( 'network' === $this->args['database'] ) {
546 $this->options = get_site_option( $this->unique );
547 } else {
548 $this->options = get_option( $this->unique );
549 }
550
551 if ( empty( $this->options ) ) {
552 $this->options = array();
553 }
554
555 return $this->options;
556
557 }
558
559 /**
560 * WP api – admin menu.
561 */
562 public function add_admin_menu() {
563 // Show plugin setting menu as per user role. – ShapedPlugin
564 // Use the hook 'sp_pc_dashboard_capability' to change user capability.
565 $menu_capability = apply_filters( 'sp_pc_dashboard_capability', 'manage_options' );
566 extract( $this->args );
567
568 if ( 'submenu' === $menu_type ) {
569
570 $menu_page = call_user_func( 'add_submenu_page', $menu_parent, $menu_title, $menu_title, $menu_capability, $menu_slug, array( &$this, 'add_options_html' ) );
571
572 } else {
573
574 $menu_page = call_user_func( 'add_menu_page', $menu_title, $menu_title, $menu_capability, $menu_slug, array( &$this, 'add_options_html' ), $menu_icon, $menu_position );
575
576 if ( ! empty( $this->args['show_sub_menu'] ) && count( $this->pre_tabs ) > 1 ) {
577
578 // create submenus.
579 $tab_key = 1;
580 foreach ( $this->pre_tabs as $section ) {
581
582 call_user_func( 'add_submenu_page', $menu_slug, $section['title'], $section['title'], $menu_capability, $menu_slug . '#tab=' . $tab_key, '__return_null' );
583
584 if ( ! empty( $section['subs'] ) ) {
585 $tab_key += ( count( $section['subs'] ) - 1 );
586 }
587
588 $tab_key++;
589
590 }
591
592 remove_submenu_page( $menu_slug, $menu_slug );
593
594 }
595
596 if ( ! empty( $menu_hidden ) ) {
597 remove_menu_page( $menu_slug );
598 }
599 }
600
601 add_action( 'load-' . $menu_page, array( &$this, 'add_page_on_load' ) );
602
603 }
604
605 /**
606 * Add page on load.
607 */
608 public function add_page_on_load() {
609
610 if ( ! empty( $this->args['contextual_help'] ) ) {
611
612 $screen = get_current_screen();
613
614 foreach ( $this->args['contextual_help'] as $tab ) {
615 $screen->add_help_tab( $tab );
616 }
617
618 if ( ! empty( $this->args['contextual_help_sidebar'] ) ) {
619 $screen->set_help_sidebar( $this->args['contextual_help_sidebar'] );
620 }
621 }
622
623 }
624
625 /**
626 * Error check function.
627 */
628 /**
629 * Error Check function
630 *
631 * @param mixed $sections The section.
632 * @param string $err The error.
633 * @return statement
634 */
635 public function error_check( $sections, $err = '' ) {
636
637 if ( ! $this->args['ajax_save'] ) {
638
639 if ( ! empty( $sections['fields'] ) ) {
640 foreach ( $sections['fields'] as $field ) {
641 if ( ! empty( $field['id'] ) ) {
642 if ( array_key_exists( $field['id'], $this->errors ) ) {
643 $err = '<span class="spf-label-error">!</span>';
644 }
645 }
646 }
647 }
648
649 if ( ! empty( $sections['subs'] ) ) {
650 foreach ( $sections['subs'] as $sub ) {
651 $err = $this->error_check( $sub, $err );
652 }
653 }
654
655 if ( ! empty( $sections['id'] ) && array_key_exists( $sections['id'], $this->errors ) ) {
656 $err = $this->errors[ $sections['id'] ];
657 }
658 }
659
660 return $err;
661 }
662
663 /**
664 * Option page html output.
665 *
666 * @return void
667 */
668 public function add_options_html() {
669
670 $has_nav = ( count( $this->pre_tabs ) > 1 ) ? true : false;
671 $show_all = ( ! $has_nav ) ? ' spf-show-all' : '';
672 $show_buttons = isset( $this->args['show_buttons'] ) ? $this->args['show_buttons'] : true;
673 $menu_slug = isset( $this->args['menu_slug'] ) ? $this->args['menu_slug'] : '';
674 $ajax_class = ( $this->args['ajax_save'] ) ? ' spf-save-ajax' : '';
675 $sticky_class = ( $this->args['sticky_header'] ) ? ' spf-sticky-header' : '';
676 $wrapper_class = ( $this->args['framework_class'] ) ? ' ' . $this->args['framework_class'] : '';
677 $theme = ( $this->args['theme'] ) ? ' spf-theme-' . $this->args['theme'] : '';
678 $class = ( $this->args['class'] ) ? ' ' . $this->args['class'] : '';
679
680 if ( 'pcp_replace_layout' === $menu_slug ) {
681 echo '<div class="wrap pcp_replace_layout_notice"><p class="spf-text-desc">To unlock the Replace Layout on The Default Blog, WooCommerce Shop, Category, Tag, Taxonomy, Search, Author, Date... Pages, and Post Types, <a target="__blank" href="https://smartpostshow.com/"><b>Upgrade To Pro</b></a></p></div>';
682 }
683
684 echo '<div class="spf spf-options' . esc_attr( $theme ) . esc_attr( $class ) . esc_attr( $wrapper_class ) . '" data-slug="' . esc_attr( $this->args['menu_slug'] ) . '" data-unique="' . esc_attr( $this->unique ) . '">';
685
686 $notice_class = ( ! empty( $this->notice ) ) ? ' spf-form-show' : '';
687 $notice_text = ( ! empty( $this->notice ) ) ? $this->notice : '';
688
689 // echo '<div class="spf-form-result spf-form-success' . esc_attr( $notice_class ) . '">' . esc_html( $notice_text ) . '</div>';
690
691 $error_class = ( ! empty( $this->errors ) ) ? ' spf-form-show' : '';
692
693 echo '<div class="spf-form-result spf-form-error' . esc_attr( $error_class ) . '">';
694 if ( ! empty( $this->errors ) ) {
695 foreach ( $this->errors as $error ) {
696 echo '<i class="spf-label-error">!</i> ' . esc_html( $error ) . '<br />';
697 }
698 }
699 echo '</div>';
700
701 echo '<div class="spf-container">';
702
703 echo '<form method="post" action="" enctype="multipart/form-data" id="spf-form" autocomplete="off">';
704
705 echo '<input type="hidden" class="spf-section-id" name="spf_transient[section]" value="1">';
706 wp_nonce_field( 'spf_options_nonce', 'spf_options_nonce' . $this->unique );
707
708 echo '<div class="spf-header' . esc_attr( $sticky_class ) . '">';
709 echo '<div class="spf-header-inner">';
710
711 echo '<div class="spf-header-left">';
712 if ( 'pcp_replace_layout' === $menu_slug ) {
713 echo '<h1><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
714 <style type="text/css">
715 .st0{fill:#D64224;}
716 </style>
717 <path class="st0" d="M0,69.3V0h69.4v18.6H18.6v50.7L0,69.3L0,69.3z M100,100H30.6V30.7H100V100z"/>
718 </svg>' . esc_html__( 'Replace Layout', 'post-carousel' ) . '</h1>';
719 } elseif ( $show_buttons ) {
720 echo '<h1><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1.4em" fill="#e1624b" height="1.4em" viewBox="0 0 288 288" enable-background="new 0 0 288 288" xml:space="preserve"><path fill="#e1624b" d="M262.102,20.977H27.615c-3.195,0-6.638,2.401-6.638,5.63v234.359c0,3.229,3.443,6.057,6.638,6.057h234.487c3.187,0,4.921-2.828,4.921-6.057V26.607C267.023,23.378,265.289,20.977,262.102,20.977z M118.37,53.441h51.26v43.571h-51.26V53.441z M55.15,53.441h51.26v43.571H55.15V53.441z M135.457,235.413H55.15v-46.134h80.307V235.413z M135.457,173.047H55.15v-46.134h80.307V173.047z M235.413,235.413h-80.307v-46.134h80.307V235.413z M235.413,173.047h-80.307v-46.134h80.307V173.047z M235.413,97.012h-51.26V53.441h51.26V97.012z"></path><line fill="none" x1="-99" y1="-84" x2="-99" y2="-57"></line><line fill="none" x1="-170" y1="61" x2="-170" y2="101"></line></svg>' . esc_html__( 'Settings', 'post-carousel' ) . '</h1>';
721 } else {
722 echo '<h1 class="export-import"><img src="' . esc_url( SP_PC_URL ) . 'admin/assets/img/import-export.svg">' . esc_html( $this->args['framework_title'] ) . '</h1>';
723 }
724 echo '</div>';
725
726 echo '<div class="spf-header-right">';
727
728 echo ( $has_nav && $this->args['show_all_options'] ) ? '<div class="spf-expand-all" title="' . esc_html__( 'show all options', 'post-carousel' ) . '"><i class="fa fa-outdent"></i></div>' : '';
729
730 echo ( $this->args['show_search'] ) ? '<div class="spf-search"><input type="text" name="spf-search" placeholder="' . esc_html__( 'Search option(s)', 'post-carousel' ) . '" autocomplete="off" /></div>' : '';
731 if ( $show_buttons ) {
732 echo '<div class="spf-buttons">';
733 echo '<input type="submit" name="' . esc_attr( $this->unique ) . '[_nonce][save]" class="button button-primary spf-save' . esc_attr( $ajax_class ) . '" value="' . esc_html__( 'Save Settings', 'post-carousel' ) . '" data-save="' . esc_html__( 'Saving...', 'post-carousel' ) . '">';
734 echo ( $this->args['show_reset_section'] ) ? '<input type="submit" name="spf_transient[reset_section]" class="button button-secondary spf-reset-section spf-confirm" value="' . esc_html__( 'Reset Tab', 'post-carousel' ) . '" data-confirm="' . esc_html__( 'Are you sure you want to reset all settings to default values?', 'post-carousel' ) . '">' : '';
735 echo ( $this->args['show_reset_all'] ) ? '<input type="submit" name="spf_transient[reset]" class="button spf-reset-all spf-confirm" value="' . esc_html__( 'Reset All', 'post-carousel' ) . '" data-confirm="' . esc_html__( 'Are you sure to reset all options?', 'post-carousel' ) . '">' : '';
736 echo '</div>';
737 }
738 echo '</div>';
739
740 echo '<div class="clear"></div>';
741 echo '</div>';
742 echo '</div>';
743
744 echo '<div class="spf-wrapper' . esc_attr( $show_all ) . '">';
745
746 if ( $has_nav ) {
747 echo '<div class="spf-nav spf-nav-options">';
748
749 echo '<ul>';
750
751 $tab_key = 1;
752
753 foreach ( $this->pre_tabs as $tab ) {
754
755 $tab_error = $this->error_check( $tab );
756 $tab_icon = ( ! empty( $tab['icon'] ) ) ? '<i class="' . $tab['icon'] . '"></i>' : '';
757
758 if ( ! empty( $tab['subs'] ) ) {
759
760 echo '<li class="spf-tab-depth-0">';
761
762 echo '<a href="#tab=' . esc_attr( $tab_key ) . '" class="spf-arrow">' . wp_kses_post( $tab_icon ) . esc_html( $tab['title'] ) . esc_html( $tab_error ) . '</a>';
763
764 echo '<ul>';
765
766 foreach ( $tab['subs'] as $sub ) {
767
768 $sub_error = $this->error_check( $sub );
769 $sub_icon = ( ! empty( $sub['icon'] ) ) ? '<i class="' . $sub['icon'] . '"></i>' : '';
770
771 echo '<li class="spf-tab-depth-1"><a id="spf-tab-link-' . esc_attr( $tab_key ) . '" href="#tab=' . esc_attr( $tab_key ) . '">' . wp_kses_post( $sub_icon ) . esc_html( $sub['title'] ) . esc_html( $sub_error ) . '</a></li>';
772
773 $tab_key++;
774 }
775
776 echo '</ul>';
777
778 echo '</li>';
779
780 } else {
781
782 echo '<li class="spf-tab-depth-0"><a id="spf-tab-link-' . esc_attr( $tab_key ) . '" href="#tab=' . esc_attr( $tab_key ) . '">' . wp_kses_post( $tab_icon ) . esc_html( $tab['title'] ) . esc_html( $tab_error ) . '</a></li>';
783
784 $tab_key++;
785 }
786 }
787
788 echo '</ul>';
789
790 echo '</div>';
791
792 }
793
794 echo '<div class="spf-content">';
795
796 echo '<div class="spf-sections">';
797
798 $section_key = 1;
799
800 foreach ( $this->pre_sections as $section ) {
801
802 $onload = ( ! $has_nav ) ? ' spf-onload' : '';
803 $section_icon = ( ! empty( $section['icon'] ) ) ? '<i class="spf-icon ' . $section['icon'] . '"></i>' : '';
804
805 echo '<div id="spf-section-' . esc_attr( $section_key ) . '" class="spf-section' . esc_attr( $onload ) . '">';
806 echo ( $has_nav ) ? '<div class="spf-section-title"><h3>' . wp_kses_post( $section_icon ) . esc_html( $section['title'] ) . '</h3></div>' : '';
807 echo ( ! empty( $section['description'] ) ) ? '<div class="spf-field spf-section-description">' . esc_html( $section['description'] ) . '</div>' : '';
808
809 if ( ! empty( $section['fields'] ) ) {
810
811 foreach ( $section['fields'] as $field ) {
812
813 $is_field_error = $this->error_check( $field );
814
815 if ( ! empty( $is_field_error ) ) {
816 $field['_error'] = $is_field_error;
817 }
818
819 $value = ( ! empty( $field['id'] ) && isset( $this->options[ $field['id'] ] ) ) ? $this->options[ $field['id'] ] : '';
820
821 SP_PC::field( $field, $value, $this->unique, 'options' );
822
823 }
824 } else {
825
826 echo '<div class="spf-no-option spf-text-muted">' . esc_html__( 'No option provided by developer.', 'post-carousel' ) . '</div>';
827
828 }
829
830 echo '</div>';
831
832 $section_key++;
833 }
834
835 echo '</div>';
836
837 echo '<div class="clear"></div>';
838
839 echo '</div>';
840
841 echo '<div class="spf-nav-background"></div>';
842
843 echo '</div>';
844
845 if ( ! empty( $this->args['show_footer'] ) ) {
846
847 echo '<div class="spf-footer">';
848
849 echo '<div class="spf-buttons">';
850 echo '<input type="submit" name="spf_transient[save]" class="button button-primary spf-save' . esc_attr( $ajax_class ) . '" value="' . esc_html__( 'Save', 'post-carousel' ) . '" data-save="' . esc_html__( 'Saving...', 'post-carousel' ) . '">';
851 echo ( $this->args['show_reset_section'] ) ? '<input type="submit" name="spf_transient[reset_section]" class="button button-secondary spf-reset-section spf-confirm" value="' . esc_html__( 'Reset Section', 'post-carousel' ) . '" data-confirm="' . esc_html__( 'Are you sure to reset this section options?', 'post-carousel' ) . '">' : '';
852 echo ( $this->args['show_reset_all'] ) ? '<input type="submit" name="spf_transient[reset]" class="button spf-reset-all spf-confirm" value="' . esc_html__( 'Reset All', 'post-carousel' ) . '" data-confirm="' . esc_html__( 'Are you sure to reset all options?', 'post-carousel' ) . '">' : '';
853 echo '</div>';
854
855 echo ( ! empty( $this->args['footer_text'] ) ) ? '<div class="spf-copyright">' . esc_html( $this->args['footer_text'] ) . '</div>' : '';
856
857 echo '<div class="clear"></div>';
858 echo '</div>';
859
860 }
861
862 echo '</form>';
863
864 echo '</div>';
865
866 echo '<div class="clear"></div>';
867
868 echo ( ! empty( $this->args['footer_after'] ) ) ? wp_kses_post( $this->args['footer_after'] ) : '';
869
870 echo '</div>';
871
872 }
873 }
874 }
875