PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 2.0.0
Adminify – White Label, Admin Menu Editor, Login Customizer v2.0.0
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / lib / adminify-framework / classes / admin-options.class.php

admin-options.class.php in Adminify – White Label, Admin Menu Editor, Login Customizer 2.0.0, at lib/adminify-framework/classes/admin-options.class.php

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