PluginProbe
StreamCast – bring live radio to your site with a sleek player / 2.2.5
StreamCast – bring live radio to your site with a sleek player v2.2.5
2.4.5 2.4.4 trunk 1.0 1.1 2.0.0 2.1.10 2.1.2 2.1.4 2.1.5 2.1.8 2.2.1 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 All 29 releases
streamcast / admin / codestar-framework / classes / admin-options.class.php

admin-options.class.php in StreamCast – bring live radio to your site with a sleek player 2.2.5, at admin/codestar-framework/classes/admin-options.class.php

666 lines 24.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php if ( ! defined( 'ABSPATH' ) ) { die; } // Cannot access directly.
2 /**
3 *
4 * Options Class
5 *
6 * @since 1.0.0
7 * @version 1.0.0
8 *
9 */
10 if ( ! class_exists( 'CSF_Options' ) ) {
11 class CSF_Options extends CSF_Abstract {
12
13 // constans
14 public $unique = '';
15 public $notice = '';
16 public $abstract = 'options';
17 public $sections = array();
18 public $options = array();
19 public $errors = array();
20 public $pre_tabs = array();
21 public $pre_fields = array();
22 public $pre_sections = array();
23 public $args = array(
24
25 // framework title
26 'framework_title' => 'Codestar Framework <small>by Codestar</small>',
27 'framework_class' => '',
28
29 // menu settings
30 'menu_title' => '',
31 'menu_slug' => '',
32 'menu_type' => 'menu',
33 'menu_capability' => 'manage_options',
34 'menu_icon' => null,
35 'menu_position' => null,
36 'menu_hidden' => false,
37 'menu_parent' => '',
38 'sub_menu_title' => '',
39
40 // menu extras
41 'show_bar_menu' => true,
42 'show_sub_menu' => true,
43 'show_in_network' => true,
44 'show_in_customizer' => false,
45
46 'show_search' => true,
47 'show_reset_all' => true,
48 'show_reset_section' => true,
49 'show_footer' => true,
50 'show_all_options' => true,
51 'show_form_warning' => true,
52 'sticky_header' => true,
53 'save_defaults' => true,
54 'ajax_save' => true,
55 'form_action' => '',
56
57 // admin bar menu settings
58 'admin_bar_menu_icon' => '',
59 'admin_bar_menu_priority' => 50,
60
61 // footer
62 'footer_text' => 'Thank you for creating with Codestar Framework',
63 'footer_after' => '',
64 'footer_credit' => '',
65
66 // database model
67 'database' => '', // options, transient, theme_mod, network
68 'transient_time' => 0,
69
70 // contextual help
71 'contextual_help' => array(),
72 'contextual_help_sidebar' => '',
73
74 // typography options
75 'enqueue_webfont' => true,
76 'async_webfont' => false,
77
78 // others
79 'output_css' => true,
80
81 // theme
82 'nav' => 'normal',
83 'theme' => 'dark',
84 'class' => '',
85
86 // external default values
87 'defaults' => array(),
88
89 );
90
91 // run framework construct
92 public function __construct( $key, $params = array() ) {
93
94 $this->unique = $key;
95 $this->args = apply_filters( "csf_{$this->unique}_args", wp_parse_args( $params['args'], $this->args ), $this );
96 $this->sections = apply_filters( "csf_{$this->unique}_sections", $params['sections'], $this );
97
98 // run only is admin panel options, avoid performance loss
99 $this->pre_tabs = $this->pre_tabs( $this->sections );
100 $this->pre_fields = $this->pre_fields( $this->sections );
101 $this->pre_sections = $this->pre_sections( $this->sections );
102
103 $this->get_options();
104 $this->set_options();
105 $this->save_defaults();
106
107 add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
108 add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_menu' ), $this->args['admin_bar_menu_priority'] );
109 add_action( 'wp_ajax_csf_'. $this->unique .'_ajax_save', array( $this, 'ajax_save' ) );
110
111 if ( $this->args['database'] === 'network' && ! empty( $this->args['show_in_network'] ) ) {
112 add_action( 'network_admin_menu', array( $this, 'add_admin_menu' ) );
113 }
114
115 // wp enqeueu for typography and output css
116 parent::__construct();
117
118 }
119
120 // instance
121 public static function instance( $key, $params = array() ) {
122 return new self( $key, $params );
123 }
124
125 // add admin bar menu
126 public function add_admin_bar_menu( $wp_admin_bar ) {
127
128 if ( ! current_user_can( $this->args['menu_capability'] ) ) {
129 return;
130 }
131
132 if ( is_network_admin() && ( $this->args['database'] !== 'network' || $this->args['show_in_network'] !== true ) ) {
133 return;
134 }
135
136 if ( ! empty( $this->args['show_bar_menu'] ) && empty( $this->args['menu_hidden'] ) ) {
137
138 global $submenu;
139
140 $menu_slug = $this->args['menu_slug'];
141 $menu_icon = ( ! empty( $this->args['admin_bar_menu_icon'] ) ) ? '<span class="csf-ab-icon ab-icon '. esc_attr( $this->args['admin_bar_menu_icon'] ) .'"></span>' : '';
142
143 $wp_admin_bar->add_node( array(
144 'id' => $menu_slug,
145 'title' => $menu_icon . esc_attr( $this->args['menu_title'] ),
146 'href' => esc_url( ( is_network_admin() ) ? network_admin_url( 'admin.php?page='. $menu_slug ) : admin_url( 'admin.php?page='. $menu_slug ) ),
147 ) );
148
149 if ( ! empty( $submenu[$menu_slug] ) ) {
150 foreach ( $submenu[$menu_slug] as $menu_key => $menu_value ) {
151 $wp_admin_bar->add_node( array(
152 'parent' => $menu_slug,
153 'id' => $menu_slug .'-'. $menu_key,
154 'title' => $menu_value[0],
155 'href' => esc_url( ( is_network_admin() ) ? network_admin_url( 'admin.php?page='. $menu_value[2] ) : admin_url( 'admin.php?page='. $menu_value[2] ) ),
156 ) );
157 }
158 }
159
160 }
161
162 }
163
164 public function ajax_save() {
165
166 $result = $this->set_options( true );
167
168 if ( ! $result ) {
169 wp_send_json_error( array( 'error' => esc_html__( 'Error while saving the changes.', 'csf' ) ) );
170 } else {
171 wp_send_json_success( array( 'notice' => $this->notice, 'errors' => $this->errors ) );
172 }
173
174 }
175
176 // get default value
177 public function get_default( $field ) {
178
179 $default = ( isset( $field['default'] ) ) ? $field['default'] : '';
180 $default = ( isset( $this->args['defaults'][$field['id']] ) ) ? $this->args['defaults'][$field['id']] : $default;
181
182 return $default;
183
184 }
185
186 // save defaults and set new fields value to main options
187 public function save_defaults() {
188
189 $tmp_options = $this->options;
190
191 foreach ( $this->pre_fields as $field ) {
192 if ( ! empty( $field['id'] ) ) {
193 $this->options[$field['id']] = ( isset( $this->options[$field['id']] ) ) ? $this->options[$field['id']] : $this->get_default( $field );
194 }
195 }
196
197 if ( $this->args['save_defaults'] && empty( $tmp_options ) ) {
198 $this->save_options( $this->options );
199 }
200
201 }
202
203 // set options
204 public function set_options( $ajax = false ) {
205
206 // XSS ok.
207 // No worries, This "POST" requests is sanitizing in the below foreach. see #L337 - #L341
208 $response = ( $ajax && ! empty( $_POST['data'] ) ) ? json_decode( wp_unslash( trim( $_POST['data'] ) ), true ) : $_POST;
209
210 // Set variables.
211 $data = array();
212 $noncekey = 'csf_options_nonce'. $this->unique;
213 $nonce = ( ! empty( $response[$noncekey] ) ) ? $response[$noncekey] : '';
214 $options = ( ! empty( $response[$this->unique] ) ) ? $response[$this->unique] : array();
215 $transient = ( ! empty( $response['csf_transient'] ) ) ? $response['csf_transient'] : array();
216
217 if ( wp_verify_nonce( $nonce, 'csf_options_nonce' ) ) {
218
219 $importing = false;
220 $section_id = ( ! empty( $transient['section'] ) ) ? $transient['section'] : '';
221
222 if ( ! $ajax && ! empty( $response[ 'csf_import_data' ] ) ) {
223
224 // XSS ok.
225 // No worries, This "POST" requests is sanitizing in the below foreach. see #L337 - #L341
226 $import_data = json_decode( wp_unslash( trim( $response[ 'csf_import_data' ] ) ), true );
227 $options = ( is_array( $import_data ) && ! empty( $import_data ) ) ? $import_data : array();
228 $importing = true;
229 $this->notice = esc_html__( 'Settings successfully imported.', 'csf' );
230
231 }
232
233 if ( ! empty( $transient['reset'] ) ) {
234
235 foreach ( $this->pre_fields as $field ) {
236 if ( ! empty( $field['id'] ) ) {
237 $data[$field['id']] = $this->get_default( $field );
238 }
239 }
240
241 $this->notice = esc_html__( 'Default settings restored.', 'csf' );
242
243 } else if ( ! empty( $transient['reset_section'] ) && ! empty( $section_id ) ) {
244
245 if ( ! empty( $this->pre_sections[$section_id-1]['fields'] ) ) {
246
247 foreach ( $this->pre_sections[$section_id-1]['fields'] as $field ) {
248 if ( ! empty( $field['id'] ) ) {
249 $data[$field['id']] = $this->get_default( $field );
250 }
251 }
252
253 }
254
255 $data = wp_parse_args( $data, $this->options );
256
257 $this->notice = esc_html__( 'Default settings restored.', 'csf' );
258
259 } else {
260
261 // sanitize and validate
262 foreach ( $this->pre_fields as $field ) {
263
264 if ( ! empty( $field['id'] ) ) {
265
266 $field_id = $field['id'];
267 $field_value = isset( $options[$field_id] ) ? $options[$field_id] : '';
268
269 // Ajax and Importing doing wp_unslash already.
270 if ( ! $ajax && ! $importing ) {
271 $field_value = wp_unslash( $field_value );
272 }
273
274 // Sanitize "post" request of field.
275 if ( ! isset( $field['sanitize'] ) ) {
276
277 if( is_array( $field_value ) ) {
278
279 $data[$field_id] = wp_kses_post_deep( $field_value );
280
281 } else {
282
283 $data[$field_id] = wp_kses_post( $field_value );
284
285 }
286
287 } else if( isset( $field['sanitize'] ) && is_callable( $field['sanitize'] ) ) {
288
289 $data[$field_id] = call_user_func( $field['sanitize'], $field_value );
290
291 } else {
292
293 $data[$field_id] = $field_value;
294
295 }
296
297 // Validate "post" request of field.
298 if ( isset( $field['validate'] ) && is_callable( $field['validate'] ) ) {
299
300 $has_validated = call_user_func( $field['validate'], $field_value );
301
302 if ( ! empty( $has_validated ) ) {
303
304 $data[$field_id] = ( isset( $this->options[$field_id] ) ) ? $this->options[$field_id] : '';
305 $this->errors[$field_id] = $has_validated;
306
307 }
308
309 }
310
311 }
312
313 }
314
315 }
316
317 $data = apply_filters( "csf_{$this->unique}_save", $data, $this );
318
319 do_action( "csf_{$this->unique}_save_before", $data, $this );
320
321 $this->options = $data;
322
323 $this->save_options( $data );
324
325 do_action( "csf_{$this->unique}_save_after", $data, $this );
326
327 if ( empty( $this->notice ) ) {
328 $this->notice = esc_html__( 'Settings saved.', 'csf' );
329 }
330
331 return true;
332
333 }
334
335 return false;
336
337 }
338
339 // save options database
340 public function save_options( $data ) {
341
342 if ( $this->args['database'] === 'transient' ) {
343 set_transient( $this->unique, $data, $this->args['transient_time'] );
344 } else if ( $this->args['database'] === 'theme_mod' ) {
345 set_theme_mod( $this->unique, $data );
346 } else if ( $this->args['database'] === 'network' ) {
347 update_site_option( $this->unique, $data );
348 } else {
349 update_option( $this->unique, $data );
350 }
351
352 do_action( "csf_{$this->unique}_saved", $data, $this );
353
354 }
355
356 // get options from database
357 public function get_options() {
358
359 if ( $this->args['database'] === 'transient' ) {
360 $this->options = get_transient( $this->unique );
361 } else if ( $this->args['database'] === 'theme_mod' ) {
362 $this->options = get_theme_mod( $this->unique );
363 } else if ( $this->args['database'] === 'network' ) {
364 $this->options = get_site_option( $this->unique );
365 } else {
366 $this->options = get_option( $this->unique );
367 }
368
369 if ( empty( $this->options ) ) {
370 $this->options = array();
371 }
372
373 return $this->options;
374
375 }
376
377 // admin menu
378 public function add_admin_menu() {
379
380 extract( $this->args );
381
382 if ( $menu_type === 'submenu' ) {
383
384 $menu_page = call_user_func( 'add_submenu_page', $menu_parent, esc_attr( $menu_title ), esc_attr( $menu_title ), $menu_capability, $menu_slug, array( $this, 'add_options_html' ) );
385
386 } else {
387
388 $menu_page = call_user_func( 'add_menu_page', esc_attr( $menu_title ), esc_attr( $menu_title ), $menu_capability, $menu_slug, array( $this, 'add_options_html' ), $menu_icon, $menu_position );
389
390 if ( ! empty( $sub_menu_title ) ) {
391 call_user_func( 'add_submenu_page', $menu_slug, esc_attr( $sub_menu_title ), esc_attr( $sub_menu_title ), $menu_capability, $menu_slug, array( $this, 'add_options_html' ) );
392 }
393
394 if ( ! empty( $this->args['show_sub_menu'] ) && count( $this->pre_tabs ) > 1 ) {
395
396 // create submenus
397 foreach ( $this->pre_tabs as $section ) {
398 call_user_func( 'add_submenu_page', $menu_slug, esc_attr( $section['title'] ), esc_attr( $section['title'] ), $menu_capability, $menu_slug .'#tab='. sanitize_title( $section['title'] ), '__return_null' );
399 }
400
401 remove_submenu_page( $menu_slug, $menu_slug );
402
403 }
404
405 if ( ! empty( $menu_hidden ) ) {
406 remove_menu_page( $menu_slug );
407 }
408
409 }
410
411 add_action( 'load-'. $menu_page, array( $this, 'add_page_on_load' ) );
412
413 }
414
415 public function add_page_on_load() {
416
417 if ( ! empty( $this->args['contextual_help'] ) ) {
418
419 $screen = get_current_screen();
420
421 foreach ( $this->args['contextual_help'] as $tab ) {
422 $screen->add_help_tab( $tab );
423 }
424
425 if ( ! empty( $this->args['contextual_help_sidebar'] ) ) {
426 $screen->set_help_sidebar( $this->args['contextual_help_sidebar'] );
427 }
428
429 }
430
431 if ( ! empty( $this->args['footer_credit'] ) ) {
432 add_filter( 'admin_footer_text', array( $this, 'add_admin_footer_text' ) );
433 }
434
435 }
436
437 public function add_admin_footer_text() {
438 echo wp_kses_post( $this->args['footer_credit'] );
439 }
440
441 public function error_check( $sections, $err = '' ) {
442
443 if ( ! $this->args['ajax_save'] ) {
444
445 if ( ! empty( $sections['fields'] ) ) {
446 foreach ( $sections['fields'] as $field ) {
447 if ( ! empty( $field['id'] ) ) {
448 if ( array_key_exists( $field['id'], $this->errors ) ) {
449 $err = '<span class="csf-label-error">!</span>';
450 }
451 }
452 }
453 }
454
455 if ( ! empty( $sections['subs'] ) ) {
456 foreach ( $sections['subs'] as $sub ) {
457 $err = $this->error_check( $sub, $err );
458 }
459 }
460
461 if ( ! empty( $sections['id'] ) && array_key_exists( $sections['id'], $this->errors ) ) {
462 $err = $this->errors[$sections['id']];
463 }
464
465 }
466
467 return $err;
468 }
469
470 // option page html output
471 public function add_options_html() {
472
473 $has_nav = ( count( $this->pre_tabs ) > 1 ) ? true : false;
474 $show_all = ( ! $has_nav ) ? ' csf-show-all' : '';
475 $ajax_class = ( $this->args['ajax_save'] ) ? ' csf-save-ajax' : '';
476 $sticky_class = ( $this->args['sticky_header'] ) ? ' csf-sticky-header' : '';
477 $wrapper_class = ( $this->args['framework_class'] ) ? ' '. $this->args['framework_class'] : '';
478 $theme = ( $this->args['theme'] ) ? ' csf-theme-'. $this->args['theme'] : '';
479 $class = ( $this->args['class'] ) ? ' '. $this->args['class'] : '';
480 $nav_type = ( $this->args['nav'] === 'inline' ) ? 'inline' : 'normal';
481 $form_action = ( $this->args['form_action'] ) ? $this->args['form_action'] : '';
482
483 do_action( 'csf_options_before' );
484
485 echo '<div class="csf csf-options'. esc_attr( $theme . $class . $wrapper_class ) .'" data-slug="'. esc_attr( $this->args['menu_slug'] ) .'" data-unique="'. esc_attr( $this->unique ) .'">';
486
487 echo '<div class="csf-container">';
488
489 echo '<form method="post" action="'. esc_attr( $form_action ) .'" enctype="multipart/form-data" id="csf-form" autocomplete="off" novalidate="novalidate">';
490
491 echo '<input type="hidden" class="csf-section-id" name="csf_transient[section]" value="1">';
492
493 wp_nonce_field( 'csf_options_nonce', 'csf_options_nonce'. $this->unique );
494
495 echo '<div class="csf-header'. esc_attr( $sticky_class ) .'">';
496 echo '<div class="csf-header-inner">';
497
498 echo '<div class="csf-header-left">';
499 echo '<h1>'. $this->args['framework_title'] .'</h1>';
500 echo '</div>';
501
502 echo '<div class="csf-header-right">';
503
504 $notice_class = ( ! empty( $this->notice ) ) ? 'csf-form-show' : '';
505 $notice_text = ( ! empty( $this->notice ) ) ? $this->notice : '';
506
507 echo '<div class="csf-form-result csf-form-success '. esc_attr( $notice_class ) .'">'. $notice_text .'</div>';
508
509 echo ( $this->args['show_form_warning'] ) ? '<div class="csf-form-result csf-form-warning">'. esc_html__( 'You have unsaved changes, save your changes!', 'csf' ) .'</div>' : '';
510
511 echo ( $has_nav && $this->args['show_all_options'] ) ? '<div class="csf-expand-all" title="'. esc_html__( 'show all settings', 'csf' ) .'"><i class="fas fa-outdent"></i></div>' : '';
512
513 echo ( $this->args['show_search'] ) ? '<div class="csf-search"><input type="text" name="csf-search" placeholder="'. esc_html__( 'Search...', 'csf' ) .'" autocomplete="off" /></div>' : '';
514
515 echo '<div class="csf-buttons">';
516 echo '<input type="submit" name="'. esc_attr( $this->unique ) .'[_nonce][save]" class="button button-primary csf-top-save csf-save'. esc_attr( $ajax_class ) .'" value="'. esc_html__( 'Save', 'csf' ) .'" data-save="'. esc_html__( 'Saving...', 'csf' ) .'">';
517 echo ( $this->args['show_reset_section'] ) ? '<input type="submit" name="csf_transient[reset_section]" class="button button-secondary csf-reset-section csf-confirm" value="'. esc_html__( 'Reset Section', 'csf' ) .'" data-confirm="'. esc_html__( 'Are you sure to reset this section options?', 'csf' ) .'">' : '';
518 echo ( $this->args['show_reset_all'] ) ? '<input type="submit" name="csf_transient[reset]" class="button csf-warning-primary csf-reset-all csf-confirm" value="'. ( ( $this->args['show_reset_section'] ) ? esc_html__( 'Reset All', 'csf' ) : esc_html__( 'Reset', 'csf' ) ) .'" data-confirm="'. esc_html__( 'Are you sure you want to reset all settings to default values?', 'csf' ) .'">' : '';
519 echo '</div>';
520
521 echo '</div>';
522
523 echo '<div class="clear"></div>';
524 echo '</div>';
525 echo '</div>';
526
527 echo '<div class="csf-wrapper'. esc_attr( $show_all ) .'">';
528
529 if ( $has_nav ) {
530
531 echo '<div class="csf-nav csf-nav-'. esc_attr( $nav_type ) .' csf-nav-options">';
532
533 echo '<ul>';
534
535 foreach ( $this->pre_tabs as $tab ) {
536
537 $tab_id = sanitize_title( $tab['title'] );
538 $tab_error = $this->error_check( $tab );
539 $tab_icon = ( ! empty( $tab['icon'] ) ) ? '<i class="csf-tab-icon '. esc_attr( $tab['icon'] ) .'"></i>' : '';
540
541 if ( ! empty( $tab['subs'] ) ) {
542
543 echo '<li class="csf-tab-item">';
544
545 echo '<a href="#tab='. esc_attr( $tab_id ) .'" data-tab-id="'. esc_attr( $tab_id ) .'" class="csf-arrow">'. $tab_icon . $tab['title'] . $tab_error .'</a>';
546
547 echo '<ul>';
548
549 foreach ( $tab['subs'] as $sub ) {
550
551 $sub_id = $tab_id .'/'. sanitize_title( $sub['title'] );
552 $sub_error = $this->error_check( $sub );
553 $sub_icon = ( ! empty( $sub['icon'] ) ) ? '<i class="csf-tab-icon '. esc_attr( $sub['icon'] ) .'"></i>' : '';
554
555 echo '<li><a href="#tab='. esc_attr( $sub_id ) .'" data-tab-id="'. esc_attr( $sub_id ) .'">'. $sub_icon . $sub['title'] . $sub_error .'</a></li>';
556
557 }
558
559 echo '</ul>';
560
561 echo '</li>';
562
563 } else {
564
565 echo '<li class="csf-tab-item"><a href="#tab='. esc_attr( $tab_id ) .'" data-tab-id="'. esc_attr( $tab_id ) .'">'. $tab_icon . $tab['title'] . $tab_error .'</a></li>';
566
567 }
568
569 }
570
571 echo '</ul>';
572
573 echo '</div>';
574
575 }
576
577 echo '<div class="csf-content">';
578
579 echo '<div class="csf-sections">';
580
581 foreach ( $this->pre_sections as $section ) {
582
583 $section_onload = ( ! $has_nav ) ? ' csf-onload' : '';
584 $section_class = ( ! empty( $section['class'] ) ) ? ' '. $section['class'] : '';
585 $section_icon = ( ! empty( $section['icon'] ) ) ? '<i class="csf-section-icon '. esc_attr( $section['icon'] ) .'"></i>' : '';
586 $section_title = ( ! empty( $section['title'] ) ) ? $section['title'] : '';
587 $section_parent = ( ! empty( $section['ptitle'] ) ) ? sanitize_title( $section['ptitle'] ) .'/' : '';
588 $section_slug = ( ! empty( $section['title'] ) ) ? sanitize_title( $section_title ) : '';
589
590 echo '<div class="csf-section hidden'. esc_attr( $section_onload . $section_class ) .'" data-section-id="'. esc_attr( $section_parent . $section_slug ) .'">';
591 echo ( $has_nav ) ? '<div class="csf-section-title"><h3>'. $section_icon . $section_title .'</h3></div>' : '';
592 echo ( ! empty( $section['description'] ) ) ? '<div class="csf-field csf-section-description">'. $section['description'] .'</div>' : '';
593
594 if ( ! empty( $section['fields'] ) ) {
595
596 foreach ( $section['fields'] as $field ) {
597
598 $is_field_error = $this->error_check( $field );
599
600 if ( ! empty( $is_field_error ) ) {
601 $field['_error'] = $is_field_error;
602 }
603
604 if ( ! empty( $field['id'] ) ) {
605 $field['default'] = $this->get_default( $field );
606 }
607
608 $value = ( ! empty( $field['id'] ) && isset( $this->options[$field['id']] ) ) ? $this->options[$field['id']] : '';
609
610 CSF::field( $field, $value, $this->unique, 'options' );
611
612 }
613
614 } else {
615
616 echo '<div class="csf-no-option">'. esc_html__( 'No data available.', 'csf' ) .'</div>';
617
618 }
619
620 echo '</div>';
621
622 }
623
624 echo '</div>';
625
626 echo '<div class="clear"></div>';
627
628 echo '</div>';
629
630 echo ( $has_nav && $nav_type === 'normal' ) ? '<div class="csf-nav-background"></div>' : '';
631
632 echo '</div>';
633
634 if ( ! empty( $this->args['show_footer'] ) ) {
635
636 echo '<div class="csf-footer">';
637
638 echo '<div class="csf-buttons">';
639 echo '<input type="submit" name="csf_transient[save]" class="button button-primary csf-save'. esc_attr( $ajax_class ) .'" value="'. esc_html__( 'Save', 'csf' ) .'" data-save="'. esc_html__( 'Saving...', 'csf' ) .'">';
640 echo ( $this->args['show_reset_section'] ) ? '<input type="submit" name="csf_transient[reset_section]" class="button button-secondary csf-reset-section csf-confirm" value="'. esc_html__( 'Reset Section', 'csf' ) .'" data-confirm="'. esc_html__( 'Are you sure to reset this section options?', 'csf' ) .'">' : '';
641 echo ( $this->args['show_reset_all'] ) ? '<input type="submit" name="csf_transient[reset]" class="button csf-warning-primary csf-reset-all csf-confirm" value="'. ( ( $this->args['show_reset_section'] ) ? esc_html__( 'Reset All', 'csf' ) : esc_html__( 'Reset', 'csf' ) ) .'" data-confirm="'. esc_html__( 'Are you sure you want to reset all settings to default values?', 'csf' ) .'">' : '';
642 echo '</div>';
643
644 echo ( ! empty( $this->args['footer_text'] ) ) ? '<div class="csf-copyright">'. $this->args['footer_text'] .'</div>' : '';
645
646 echo '<div class="clear"></div>';
647 echo '</div>';
648
649 }
650
651 echo '</form>';
652
653 echo '</div>';
654
655 echo '<div class="clear"></div>';
656
657 echo ( ! empty( $this->args['footer_after'] ) ) ? $this->args['footer_after'] : '';
658
659 echo '</div>';
660
661 do_action( 'csf_options_after' );
662
663 }
664 }
665 }
666