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